内核中文件操作
文章目录
文件操作也是比较有用的功能, 而且这部分功能也比较有用. 当然全部记录下来也没有什么营养. 学内核还是要学内核的架构. 关于这个函数的使用. 我觉得不经常使用的使用一次就可以了. 就像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