一. 在驅(qū)動(dòng)中使用文件
在Windows執(zhí)行體中,通過文件對象來代表文件,該文件對象是一種由對象管理器管理的執(zhí)行體對象。例如:目錄也是由文件對象代表的。
內(nèi)核組件通過對象名來引用文件,即在文件的全路徑前面加\DosDevices。(在Windows 2000及后續(xù)操作系統(tǒng)中,\??等同于\DosDevices)。例如,文件C:\WINDOWS\example.txt的對象名為\DosDevices\C:\WINDOWS\example.txt。你需要用對象名來打開文件以獲取句柄。
對象名在下面會(huì)講述。
使用文件步驟:
- 打開文件返回文件句柄。
- 調(diào)用合適的ZwXxxFile 函數(shù)以完成對文件的操作。
- 調(diào)用ZwClose函數(shù)關(guān)閉打開的文件句柄。
當(dāng)打開一個(gè)指向文件的文件句柄時(shí),Windows執(zhí)行體就創(chuàng)建了一個(gè)文件對象來代表該文件,同時(shí)返回一個(gè)代表該對象的文件句柄。因此,對于單個(gè)文件來說,會(huì)存在多個(gè)文件對象的情況。同樣,由于用戶模式的應(yīng)用程序可能會(huì)復(fù)制文件句柄,因此,對于同一個(gè)文件對象,也會(huì)存在多個(gè)文件句柄。只有當(dāng)所有指向一個(gè)文件對象的文件句柄都關(guān)閉后,Windows執(zhí)行體才會(huì)刪除該文件對象。
二. 對象名
內(nèi)核模式的對象可以是具名的或者是無名的。對象名是一個(gè)Unicode字符串,不管是用戶模式還是內(nèi)核模式,都可以額用它來引用對象。例如,\KernelObjects\LowMemoryCondition是一個(gè)指示在系統(tǒng)中總的可用內(nèi)存偏低的標(biāo)準(zhǔn)事件對象名稱。
用戶模式和內(nèi)核模式都利用對象名來打開指向?qū)ο蟮木浔K械暮罄m(xù)操作都需要用該打開的句柄來完成。
如果對象是無名的,用戶模式的組件無法打開指向該對象的句柄。內(nèi)核模式則不同,它可以通過指針或句柄來引用無名對象。
具名對象被組織成層狀結(jié)構(gòu)。每個(gè)對象的命名同其父對象有關(guān)系。每個(gè)組件的對象名以反斜杠開頭。例如,\KernelObjects對象是\KernelObjects\LowMemoryCondition對象的父對象。
只有某些類型的對象才擁有子對象。下面列出其中的一部分:
1. 目錄對象。對象管理器利用目錄對象管理對象,例如,\KernelObjects是一個(gè)目錄對象,它用來維護(hù)標(biāo)準(zhǔn)事件對象。目錄對象不與真實(shí)的磁盤目錄相對應(yīng)。這里,目錄的意思不是普通我們講的文件夾目錄的意思。
2. 磁盤驅(qū)動(dòng)設(shè)備對象。這與磁盤文件(含常規(guī)目錄)相對應(yīng)。
3. 代表目錄的文件對象。對應(yīng)指定目錄下的所有文件,此處的目錄同常規(guī)理解的目錄相同。
4. WDM驅(qū)動(dòng)設(shè)備對象,具有自己的命名空間,可以用在驅(qū)動(dòng)定義的方式中。
文件具有對象名,其命名與\DosDevices有關(guān)。例如,文件C:\Directory\File的對象名為\DosDevices\C:\Directory\File。
下表描述了一組典型的對象名
對象名
|
描述
|
\DosDevices
|
對象目錄
|
\DosDevices\C:
|
代表C盤的設(shè)備對象
|
\DosDevices\C:\Directory
|
代表名為C:\Director的文件對象
|
\DosDevices\C:\Directory\File
|
代表名為C:\Directo\Filer的文件對象
|
驅(qū)動(dòng)可以在指定的對象目錄中創(chuàng)建具名對象
三. 打開指向文件的句柄
按如下步驟來打開指向文件的句柄:
1. 定義各一個(gè)OBJECT_ATTRIBUTES結(jié)構(gòu)體變量,然后調(diào)用InitializeObjectAttributes函數(shù)初始化該變量。關(guān)鍵是設(shè)置改變量的ObjectName字段為文件對象名。
2. 調(diào)用IoCreateFile, ZwCreateFile, 或者 ZwOpenFile,傳遞上面定義的結(jié)構(gòu)體變量,成功就會(huì)返回執(zhí)行該文件的句柄。
注:驅(qū)動(dòng)一般用ZwCreateFile和ZwOpenFile,IoCreateFile很少使用
當(dāng)調(diào)用ZwCreateFile,ZwOpenFile或IoCreateFile時(shí),Windows執(zhí)行體創(chuàng)建一個(gè)代表該文件的新的文件對象,并返回一個(gè)指向該對象的句柄。文件對象一直存在,知道你關(guān)閉了所有指向它的文件句柄。
四. 使用文件句柄操作文件
下表列出了驅(qū)動(dòng)中常用的利用文件句柄操作文件的函數(shù)
操作
|
函數(shù)
|
讀文件
|
ZwReadFile
|
寫文件
|
ZwWriteFile
|
讀文件熟悉
|
ZwQueryInformationFile
|
設(shè)置文件熟悉
|
ZwSetInformationFile
|
五. 驅(qū)動(dòng)中使用文件代碼示例

/**//** @file
*Copyright(C): Information Technology Co Ltd., All rights reserved.
*@n
*@n 文件: MyKFile.h
*@n 功能: 處理內(nèi)核文件的操作
*@n 作者: aurain(zhangqiushui@gmail.com) 2009-12-31
*/
#ifndef __MYKFILE_H__
#define __MYKFILE_H__

#include "debug.h"


/**//**
* 創(chuàng)建或打開文件
* @param lpFileHandle 返回打開的文件句柄指針
* @param usFileName 需要打開的文件路徑,使用對象路徑,如\\??\\c:\test.txt
* @param dwDesiredAccess 申請權(quán)限,可以用|(或)組合以下操作
寫文件內(nèi)容-FILE_WRITE_DATA,設(shè)置文件熟悉-FILE_WRITE_ATTRIBUTES,通用寫-GENERIC_WRITE
讀文件內(nèi)容-FILE_READ_DATA,設(shè)置文件熟悉-FILE_READE_ATTRIBUTES,通用寫-GENERIC_READ
刪除文件-DELETE
全部權(quán)限-GENERIC_ALL
同步打開文件-SYNCHRONIZE
* @param dwShareAccess 共享方式(是指本代碼打開這個(gè)文件時(shí),允許別的代碼同時(shí)打開這個(gè)文件所具有的權(quán)限
可以用|(或)組合以下操作
共享讀-FILE_SHARE_READ
共享寫-FILE_SHARE_WRITE
共享刪除-FILE_SHARE_DELETE
* @param dwCreateDisposition 創(chuàng)建或打開文件的目的
新建文件-FILE_CREATE
打開文件-FILE_OPEN
打開或新建-FILE_OPEN_IF
覆蓋-FILE_OVERWRITE
新建或覆蓋-FILE_OVERWRITE_IF
新建或取代-FILE_SUPERSEDE
* @param dwCreateOptions 打開文件時(shí)選項(xiàng)設(shè)置
一般用FILE_NOT_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
* @return 讀取成功: STATUS_SUCCESS;讀取失敗:NTSTATUS error code
*/
__inline
NTSTATUS MyCreateFile(OUT PHANDLE lpFileHandle,
IN PUNICODE_STRING usFileName,
IN ULONG dwDesiredAccess,
IN ULONG dwShareAccess,
IN ULONG dwCreateDisposition,
IN ULONG dwCreateOptions)


{
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
OBJECT_ATTRIBUTES oaName;
IO_STATUS_BLOCK iosBlock;
if (lpFileHandle != NULL && usFileName != NULL && usFileName->Buffer != NULL)

{
if (PASSIVE_LEVEL != KeGetCurrentIrql())

{
return ntStatus;
}
InitializeObjectAttributes(&oaName,
usFileName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
ntStatus = ZwCreateFile(lpFileHandle,
dwDesiredAccess,
&oaName,
&iosBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
dwShareAccess,
dwCreateDisposition,
dwCreateOptions,
NULL,
0);
if (!NT_SUCCESS(ntStatus))

{
DEBUG_ERROR(("[MyCreateFile]ZwCreateFile(%ws)failed with error:%08x\r\n", usFileName->Buffer, ntStatus));
return ntStatus;
}
}
return ntStatus;
}


/**//**
* 關(guān)閉打開的文件句柄
* @param hFile 文件句柄
* @return 讀取成功: STATUS_SUCCESS;讀取失敗:NTSTATUS error code
*/
__inline
NTSTATUS MyCloseFile(IN HANDLE hFile)


{
return ZwClose(hFile);
}


/**//**
* 讀取文件內(nèi)容
* @param hFile 文件句柄
* @param pBuffer 緩沖區(qū)
* @param ulBufferSize 緩沖區(qū)大小
* @param pulBytesRead 實(shí)際讀取的大小
* @return 讀取成功: STATUS_SUCCESS;讀取失敗:NTSTATUS error code
*/
__inline
NTSTATUS MyReadFile(IN HANDLE hFile,
IN PVOID pBuffer,
IN ULONG ulBufferSize,
OUT PULONG pulBytesRead)


{
IO_STATUS_BLOCK iosBlock;
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;

if (hFile == NULL || pBuffer == NULL)

{
return ntStatus;
}
if( PASSIVE_LEVEL < KeGetCurrentIrql())

{
DEBUG_ERROR(("All kernel file operating functions must running on PASSIVE_LEVEL\r\n"));

return ntStatus;
}

*pulBytesRead = 0;

ntStatus = ZwReadFile(hFile,
NULL,
NULL,
NULL,
&iosBlock,
pBuffer,
ulBufferSize,
NULL,
NULL);

if (NT_SUCCESS(ntStatus))

{
//獲取實(shí)際讀取到的大小
*pulBytesRead = (ULONG)iosBlock.Information;
}
else

{
DEBUG_ERROR(("[MyReadFile]ZwReadFile failed with:%08x\r\n", ntStatus));
}

return ntStatus;
}


/**//**
* 向文件寫入內(nèi)容
* @param hFile 文件句柄
* @param pBuffer 緩沖區(qū)
* @param ulBufferSize 緩沖區(qū)大小
* @param pulBytesWrite 實(shí)際寫入的大小
* @return 讀取成功: STATUS_SUCCESS;讀取失敗:NTSTATUS error code
*/
__inline
NTSTATUS MyWriteFile(IN HANDLE hFile,
IN PVOID pBuffer,
IN ULONG ulBufferSize,
OUT PULONG pulBytesWrite)


{
IO_STATUS_BLOCK iosBlock;
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
if (hFile == NULL || pBuffer == NULL)

{
return ntStatus;
}

// All kernel file operating functions must running on PASSIVE_LEVEL
if (PASSIVE_LEVEL != KeGetCurrentIrql())

{
return ntStatus;
}

*pulBytesWrite = 0;

ntStatus = ZwWriteFile(hFile,
NULL,
NULL,
NULL,
&iosBlock,
pBuffer,
ulBufferSize,
NULL,
NULL);

if (NT_SUCCESS(ntStatus))

{
*pulBytesWrite = (ULONG)iosBlock.Information;
}
else

{
DEBUG_ERROR(("[MyWriteFile]ZwWriteFile failed with:%08x\r\n", ntStatus));
}

return ntStatus;
}

#endif
posted on 2009-12-31 15:27
水 閱讀(10266)
評(píng)論(1) 編輯 收藏 引用 所屬分類:
windows驅(qū)動(dòng)