内核中文件操作
文章目录
文件操作也是比较有用的功能, 而且这部分功能也比较有用. 当然全部记录下来也没有什么营养. 学内核还是要学内核的架构. 关于这个函数的使用. 我觉得不经常使用的使用一次就可以了. 就像Win32下面的函数. 很多基本都用不上. 不过也没有什么问题!! 能够查就行. 不过一些非常常用的函数还查. 就有点….所以函数应该把套路稍微记下..
没有什么好说的, 直接上代码:
```c++
/*
Windows内核下文件操作!
编译方法参见makefile.
*/
#include
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
// 或者写成 "\\Device\\HarddiskVolume1\\1.LOG";
UNICODE_STRING UStFileName = RTL_CONSTANT_STRING( "\\??\\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;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
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;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
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);
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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/%dn”, // 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 }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
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;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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; |
}
文章作者 忆杰
上次更新 2011-10-11