内核中文件操作

文件操作也是比较有用的功能, 而且这部分功能也比较有用. 当然全部记录下来也没有什么营养. 学内核还是要学内核的架构. 关于这个函数的使用. 我觉得不经常使用的使用一次就可以了. 就像Win32下面的函数. 很多基本都用不上. 不过也没有什么问题!! 能够查就行. 不过一些非常常用的函数还查. 就有点….所以函数应该把套路稍微记下..

 

没有什么好说的, 直接上代码:

/*
	Windows内核下文件操作!
	编译方法参见makefile.
*/
#include <ntddk.h>
#define BUFFER_SIZE 1024
//===========================================================================
//写入文件试验
NTSTATUS CreateWriteFileTest() {
	HANDLE hFile = NULL;
	PUCHAR pBuffer = NULL;
	NTSTATUS Status;
	LARGE_INTEGER L_number;
	IO_STATUS_BLOCK Io_Status;
	OBJECT_ATTRIBUTES Obj_Attributes;
	//或者写成 "\\Device\\HarddiskVolume1\\1.LOG"
	UNICODE_STRING UStFileName = RTL_CONSTANT_STRING( L"\\??\\C:\\Joen.log" );

	do {
		//初始化objectAttributes 对大小写敏感
		InitializeObjectAttributes( &Obj_Attributes,&UStFileName, OBJ_CASE_INSENSITIVE,	NULL, NULL );

		//打开文件, 用于重写.文件不存在返回错误.同时会覆盖原来文件的内容
		Status = ZwCreateFile( &hFile, GENERIC_WRITE,&Obj_Attributes, &Io_Status, NULL,FILE_ATTRIBUTE_NORMAL,
			FILE_SHARE_WRITE,FILE_OVERWRITE,FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
		if ( !NT_SUCCESS(Status) ) {

			//创建文件, 即使存在该文件存在.也创建覆盖
			Status = ZwCreateFile( &hFile, GENERIC_WRITE,&Obj_Attributes, &Io_Status, NULL,FILE_ATTRIBUTE_NORMAL,
				FILE_SHARE_WRITE,FILE_OPEN_IF,FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
			if ( !NT_SUCCESS(Status) ) {
				break;
			}
		}

		//分配内存
		pBuffer = (PUCHAR)ExAllocatePool(PagedPool, BUFFER_SIZE );
		if ( !pBuffer ) {
			KdPrint(( "内存分配失败!\n" ));
			Status = STATUS_UNSUCCESSFUL;
			break;
		}

		//构造要填充的数据
		RtlFillMemory( pBuffer,BUFFER_SIZE,'J' );

		//写文件
		Status = ZwWriteFile( hFile,NULL,NULL,NULL,&Io_Status, pBuffer,BUFFER_SIZE, NULL, NULL );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "WriteFile Error!\n" ));
			break;
		}else {
			KdPrint(( "文件写入长度%d!\n",Io_Status.Information ));
		}	

		//构造要填充的数据
		RtlFillMemory(pBuffer,BUFFER_SIZE,'0' );

		//追加数据, 设置文件偏移指针64位的
		L_number.QuadPart = 1024i64;

		//对文件进行附加写
		Status = ZwWriteFile( hFile, NULL, NULL, NULL, &Io_Status, pBuffer, BUFFER_SIZE, &L_number, NULL );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "文件写入失败!\n" ));
			break;
		}else {
			KdPrint(( "文件写入长度%d!\n",Io_Status.Information ));
		}

		Status = STATUS_SUCCESS;
	}while ( FALSE );

	//关闭文件句柄
	if ( hFile ) {
		ZwClose( hFile );
	}
	if ( pBuffer ) {
		ExFreePool(pBuffer);
	}
	return Status;
}
//===========================================================================
//打开文件进行追加内容试验
NTSTATUS OpenWriteFileTest() {
	HANDLE hFile = NULL;
	PUCHAR pBuffer = NULL;
	NTSTATUS Status;
	IO_STATUS_BLOCK Io_Status;
	OBJECT_ATTRIBUTES Obj_Attributes;
	//或者写成 "\\Device\\HarddiskVolume1\\1.LOG"
	UNICODE_STRING UStFileName = RTL_CONSTANT_STRING( L"\\??\\C:\\Joen.log" );
	FILE_STANDARD_INFORMATION File_Information;

	do {
		//初始化objectAttributes 对大小写敏感
		InitializeObjectAttributes( &Obj_Attributes,&UStFileName, OBJ_CASE_INSENSITIVE,	NULL, NULL );

		//打开文件, 进行读取, 文件不存在会返回错误. 同时对文件进行追加
		Status = ZwOpenFile( &hFile, GENERIC_ALL,&Obj_Attributes, &Io_Status,
			FILE_SHARE_READ|FILE_SHARE_WRITE,FILE_SYNCHRONOUS_IO_NONALERT );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "打开文件失败!\n" ));
			break;
		}

		//分配内存
		pBuffer = (PUCHAR)ExAllocatePool(PagedPool, BUFFER_SIZE );
		if ( !pBuffer ) {
			KdPrint(( "内存分配失败!\n" ));
			Status = STATUS_UNSUCCESSFUL;
			break;
		}

		//读取文件
		Status = ZwReadFile( hFile,NULL,NULL,NULL,&Io_Status,pBuffer,BUFFER_SIZE,NULL,NULL);
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "读取文件失败!\n" ));
			break;
		}

		//构造要填充的数据
		RtlFillMemory( pBuffer, BUFFER_SIZE,'e' );

		//查询文件长度
		Status = ZwQueryInformationFile( hFile,	&Io_Status,&File_Information,
			sizeof(FILE_STANDARD_INFORMATION),FileStandardInformation );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "查询文件长度失败!\n" ));
			break;
		}else {
			KdPrint(( "文件长度%d\n", File_Information.EndOfFile.QuadPart ));
		}

		//文件长度中间扩展下(根据实验扩展出来都是0)
		File_Information.EndOfFile.QuadPart+= 1024;

		//修改当前文件指针
		Status = ZwSetInformationFile( hFile,	&Io_Status,&File_Information.EndOfFile.QuadPart,
			sizeof(FILE_POSITION_INFORMATION),FilePositionInformation);
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "设置文件长度失败!\n" ));
		}

		//写文件
		Status = ZwWriteFile( hFile,NULL,NULL,NULL,&Io_Status, pBuffer,BUFFER_SIZE,
			&File_Information.EndOfFile, NULL );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "写入文件失败!\n" ));
			break;
		}else {
			KdPrint(( "文件真正写入文件长度 %d\n", Io_Status.Information ));
		}

		//构造要填充的数据
		RtlFillMemory(pBuffer,BUFFER_SIZE,'n' );

		//查询文件长度
		Status = ZwQueryInformationFile( hFile,	&Io_Status,&File_Information,
			sizeof(FILE_STANDARD_INFORMATION),FileStandardInformation );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "查询文件长度失败!\n" ));
			break;
		}else {
			KdPrint(( "文件长度%d\n", File_Information.EndOfFile.QuadPart ));
		}

		//对文件进行附加写
		Status = ZwWriteFile( hFile, NULL, NULL, NULL, &Io_Status, pBuffer, BUFFER_SIZE,
			&File_Information.EndOfFile, NULL );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "文件写入错误!\n" ));
			break;
		}
		Status = STATUS_SUCCESS;
	}while ( FALSE );

	//关闭文件句柄
	if ( hFile ) {
		ZwClose( hFile );
	}
	if ( pBuffer ) {
		ExFreePool(pBuffer);
	}
	return Status;
}
//===========================================================================
//文件属性测试
NTSTATUS FileAttributeTest() {
	HANDLE hFile = NULL;
	NTSTATUS Status;
	IO_STATUS_BLOCK Io_Status;
#if DBG
	TIME_FIELDS SysTime = {0};
#endif
	OBJECT_ATTRIBUTES Obj_Attributes;
	UNICODE_STRING UStFileName = RTL_CONSTANT_STRING( L"\\??\\C:\\Joen.log" );
	FILE_BASIC_INFORMATION		File_BasicInfo = {0};
	PFILE_NAME_INFORMATION		pFile_NameInfo = NULL;
	FILE_STANDARD_INFORMATION	File_StdInfo;
	FILE_POSITION_INFORMATION	File_PostInfo;

	do {
		//初始化objectAttributes 对大小写敏感
		InitializeObjectAttributes( &Obj_Attributes,&UStFileName, OBJ_CASE_INSENSITIVE,	NULL, NULL );

		//打开文件, 进行读取, 文件不存在会返回错误. 同时对文件进行追加
		Status = ZwOpenFile( &hFile, GENERIC_ALL,&Obj_Attributes, &Io_Status,
			FILE_SHARE_READ|FILE_SHARE_WRITE,FILE_SYNCHRONOUS_IO_NONALERT );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "打开文件失败!\n" ));
			break;
		}

		//查询文件长度, 这里假设文件长度不会超过4G了
		Status = ZwQueryInformationFile( hFile,	&Io_Status, &File_StdInfo,
			sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "查询文件信息失败!\n" ));
			break;
		}else {
			KdPrint(( "文件占用族大小: %d, 距离文件结尾还有%d个字节(文件长度).多少个链接文件%d, 是否准备删除%d, 是否是目录%d\n",
				File_StdInfo.AllocationSize.LowPart, File_StdInfo.EndOfFile.LowPart,
				File_StdInfo.NumberOfLinks,
				File_StdInfo.DeletePending, File_StdInfo.Directory ));
		}

		//查询文件时间信息, 和属性. 当然也可以设置
		Status = ZwQueryInformationFile( hFile,	&Io_Status, &File_BasicInfo,
			sizeof(FILE_BASIC_INFORMATION),FileBasicInformation );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "查询文件信息失败!\n" ));
			break;
		}else {
#if DBG
			//系统时间转成本地时间
			ExSystemTimeToLocalTime(&File_BasicInfo.CreationTime, &File_BasicInfo.CreationTime);
			ExSystemTimeToLocalTime(&File_BasicInfo.LastAccessTime, &File_BasicInfo.LastAccessTime);
			ExSystemTimeToLocalTime(&File_BasicInfo.LastWriteTime, &File_BasicInfo.LastWriteTime);

			KdPrint(( "年/月/日   时/分/秒 \n" ));
			RtlTimeToTimeFields( &File_BasicInfo.CreationTime, &SysTime );
			KdPrint(( "文件创建的时间:   %d/%d/%d   %d:%d:%d\n",
				SysTime.Year, SysTime.Month, SysTime.Day, SysTime.Hour, SysTime.Minute, SysTime.Second ));

			//最后访问时间是只有日期的..
			RtlTimeToTimeFields( &File_BasicInfo.LastAccessTime, &SysTime );
			KdPrint(( "文件最后访问时间: %d/%d/%d   %d:%d:%d\n",
				SysTime.Year, SysTime.Month, SysTime.Day, SysTime.Hour, SysTime.Minute, SysTime.Second ));

			RtlTimeToTimeFields( &File_BasicInfo.LastWriteTime, &SysTime );
			KdPrint(( "文件最后写时间:   %d/%d/%d   %d:%d:%d\n",
				SysTime.Year, SysTime.Month, SysTime.Day, SysTime.Hour, SysTime.Minute, SysTime.Second ));

// 			RtlTimeToTimeFields( &File_BasicInfo.ChangeTime, &SysTime );
// 			KdPrint(( "修改修改时间: %d/%d/%d   %d/%d/%d\n",
// 				SysTime.Year, SysTime.Month, SysTime.Day, SysTime.Hour, SysTime.Minute, SysTime.Second ));
//
			if ( File_BasicInfo.FileAttributes & FILE_ATTRIBUTE_ARCHIVE ) {
				KdPrint(( "文件是一个普通文件\n" ));
			}
			if ( File_BasicInfo.FileAttributes & FILE_ATTRIBUTE_NORMAL ) {
				KdPrint(( "文件没有设置属性\n" ));
			}
			if ( File_BasicInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY ){
				KdPrint(( "文件是一个目录\n" ));
			}
			if ( File_BasicInfo.FileAttributes & FILE_ATTRIBUTE_READONLY ) {
				KdPrint(( "文件是只读的\n" ));
			}
			if( File_BasicInfo.FileAttributes & FILE_ATTRIBUTE_HIDDEN ) {
				KdPrint(( "文件是隐藏的\n" ));
			}
			if( File_BasicInfo.FileAttributes & FILE_ATTRIBUTE_SYSTEM ) {
				KdPrint(( "文件是系统文件\n" ));
			}
#endif
		}

		pFile_NameInfo = (PFILE_NAME_INFORMATION)ExAllocatePool(PagedPool, BUFFER_SIZE );
		if ( !pFile_NameInfo ) {
			KdPrint(( "内存分配失败!\n" ));
			break;
		}
		RtlZeroMemory( pFile_NameInfo,BUFFER_SIZE );
		pFile_NameInfo->FileNameLength = BUFFER_SIZE;

		//查询文件名称信息
		Status = ZwQueryInformationFile( hFile,	&Io_Status, pFile_NameInfo,
			BUFFER_SIZE,FileNameInformation );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "查询文件名称信息失败!\n" ));
			break;
		}else {
			KdPrint(( "文件名称长度:%d, 文件名称:%ws \n", pFile_NameInfo->FileNameLength,
				pFile_NameInfo->FileName ));
		}

		//修改当前文件指针, 当然也是可以查询的
		File_PostInfo.CurrentByteOffset.QuadPart = 100i64;
		Status = ZwSetInformationFile( hFile, &Io_Status,&File_PostInfo,
			sizeof(FILE_POSITION_INFORMATION),FilePositionInformation );
		if ( !NT_SUCCESS(Status) ) {
			KdPrint(( "设置文件当前指针失败\n" ));
		}else {
			KdPrint(( "设置文件当前指针成功\n" ));
		}
	} while ( FALSE );

	if ( hFile ) {
		ZwClose( hFile );
	}
	if ( pFile_NameInfo ) {
		ExFreePool( pFile_NameInfo );
	}
	return Status;
}

NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pUSzReg ) {
	NTSTATUS Status;

	Status = CreateWriteFileTest();			//创建新文件写入试验
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "CreateWriteFileTest调用遇到错误!" ));
		return Status;
	}

	Status = OpenWriteFileTest();			//打开文件进行追加写入文件
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "OpenWriteFileTest 调用遇到错误!" ));
		return Status;
	}

	Status = FileAttributeTest();			//文件属性设置
	if ( !NT_SUCCESS(Status) ) {
		KdPrint(( "FileAttributeTest 调用遇到错误!" ));
		return Status;
	}
	return -1;
}

 

发表评论

发表评论前,请选对水果: 葡萄