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

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

```c++ /* Windows内核下文件操作! 编译方法参见makefile. */ #include ; #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;

 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;

}