2011年1月5日 星期三

[ Windows DDP ] Windows 內核函式 : 檔案操作


前言 :
在驅動程式開發中, 經常會對檔案進行操作, 與 Win32 API 不同, DDK 提供另一套對檔案的操作函式.

檔案新建 :
對檔案的新建或者打開都是透過內核函式 ZwCreateFile 實作的. 和 Windows API 類似, 這個內核函式返回一個檔案控制程式碼. 檔的所有操作都是依靠這個控制碼進行操作的. 在檔案操作完畢後, 需要關閉這個控制碼 :
- Syntax :
  1. NTSTATUS ZwCreateFile(  
  2.   __out     PHANDLE FileHandle,  
  3.   __in      ACCESS_MASK DesiredAccess,  
  4.   __in      POBJECT_ATTRIBUTES ObjectAttributes,  
  5.   __out     PIO_STATUS_BLOCK IoStatusBlock,  
  6.   __in_opt  PLARGE_INTEGER AllocationSize,  
  7.   __in      ULONG FileAttributes,  
  8.   __in      ULONG ShareAccess,  
  9.   __in      ULONG CreateDisposition,  
  10.   __in      ULONG CreateOptions,  
  11.   __in_opt  PVOID EaBuffer,  
  12.   __in      ULONG EaLength  
  13. );  

參數說明 :
* FileHandle : 返回打開的控制碼.
* DesiredAccess : 對打開檔案操作的描述, 讀, 寫或是其他. 一般指定為 GENERIC_READ 或 GENERIC_WRITE.
* ObjectAttributes : 是 OBJECT_ATTRIBUTES 結構位址, 該結構包含要打開的檔案名.
* IoStatusBlock : 指向一個 IO_STATUS_BLOCK 結構, 該結構接收 ZwCreateFile 操作的結果狀態.
* AllocationSize : 是一個指標, 指向一個 64 位元整數, 該數指定檔初始分配的大小. 該參數僅關係到新建或重寫檔案操作, 如果忽略它, 那麼檔案長度從0 開始並隨寫入增大.
* FileAttributes : 0 或 FILE_ATTRIBUTE_NORMAL, 指定新建檔案的屬性.
* ShareAccess : FILE_SHARE_READ 或 0, 指定檔案的共用方式. 如果僅為讀資料而打開檔, 則可以與其他執行緒同時讀取該檔. 如果為寫資料而打開檔, 可能不希望其他執行緒訪問該檔.
* CreateDisposition : FILE_OPEN 或 FILE_OVERWRITE_IF. 表明當指定檔案不存在或存在應該如何處理.
* CreateOptions : FILE_SYNCHRONOUS_IO_NONALERT, 指定控制打開操作和控制碼使用的附加旗標位元.
* EaBuffer : 一個指標, 指向可選的擴充屬性區.
* EaLength : 擴充屬性區的長度

這個函式需要填寫 CreateDisposition 參數. 如果想打開檔, CreateDisposition 參數設置成 FILE_OPEN, 如果想新建檔案, CreateDisposition 參數設置成 FILE_OVERWRITE_IF. 此時無論檔案是否存在, 都會新建新檔案.
檔案名稱的指定是透過設定第三個參數 ObjectAttributes. 這個參數是一個 OBJECT_ATTRIBUTES 結構, DDK 提供對該結構初始化的巨集 InitializeObjectAttributes :
- Syntax :
  1. VOID InitializeObjectAttributes(  
  2.   [out]           POBJECT_ATTRIBUTES InitializedAttributes,  
  3.   [in]            PUNICODE_STRING ObjectName,  
  4.   [in]            ULONG Attributes,  
  5.   [in]            HANDLE RootDirectory,  
  6.   [in, optional]  PSECURITY_DESCRIPTOR SecurityDescriptor  
  7. );  

參數說明 :
* InitializeAttributes : 返回的 OBJECT_ATTRIBUTES 結構.
* ObjectName : 物件名稱, 用 UNICODE_STRING 描述, 這裡設置的是檔案名.
* Attributes : 一般設為 OBJ_CASE_INSENSITIVE, 對大小寫敏感.
* RootDirectory : 一般設為 NULL
* SecurityDescriptor : 一般設為 NULL

另外檔名必須是符號連結或者是設備名. 符號連結拿磁碟代號 "C:" 來說, 就應該用 "\??\C:" 代替, 也就是說 "C:\1.log" 要寫成 "\??\C:\1.log". 其中 "\??\C:" 是符號連結, 內核會將它轉換成設備名 "\Device\HarddiskVolume1", 下面代碼演式如何在驅動程式中新建檔和打開檔 :
- 範例代碼 : (1) 新建檔案
  1. #pragma INITCODE  
  2. VOID CreateFileTest()   
  3. {  
  4.     OBJECT_ATTRIBUTES objectAttributes;  
  5.     IO_STATUS_BLOCK iostatus;  
  6.     HANDLE hfile;  
  7.     UNICODE_STRING logFileUnicodeString;  
  8.   
  9.     //初始化UNICODE_STRING字串  
  10.     RtlInitUnicodeString( &logFileUnicodeString,   
  11.         L"\\??\\C:\\1.log");  
  12.     //或者寫成 "\\Device\\HarddiskVolume1\\1.LOG"  
  13.   
  14.   
  15.     //初始化objectAttributes  
  16.     InitializeObjectAttributes(&objectAttributes,   
  17.                             &logFileUnicodeString,  
  18.                             OBJ_CASE_INSENSITIVE,   
  19.                             NULL,   
  20.                             NULL );  
  21.   
  22.     //新建檔案  
  23.     NTSTATUS ntStatus = ZwCreateFile( &hfile,   
  24.                             GENERIC_WRITE,  
  25.                             &objectAttributes,   
  26.                             &iostatus,   
  27.                             NULL,  
  28.                             FILE_ATTRIBUTE_NORMAL,   
  29.                             FILE_SHARE_READ,  
  30.                             FILE_OPEN_IF,     
  31.                             FILE_SYNCHRONOUS_IO_NONALERT,   
  32.                             NULL,   
  33.                             0 );  
  34.     if ( NT_SUCCESS(ntStatus))  
  35.     {  
  36.         KdPrint(("Create file succussfully!\n"));  
  37.     }else  
  38.     {  
  39.         KdPrint(("Create file  unsuccessfully!\n"));  
  40.     }  
  41.   
  42.     //檔案操作  
  43.     //.......  
  44.   
  45.     //關閉檔案控制代碼  
  46.     ZwClose(hfile);  
  47. }  

- 範例代碼 : (2) 打開檔案
  1. #pragma INITCODE  
  2. VOID OpenFileTest1()   
  3. {  
  4.     OBJECT_ATTRIBUTES objectAttributes;  
  5.     IO_STATUS_BLOCK iostatus;  
  6.     HANDLE hfile;  
  7.     UNICODE_STRING logFileUnicodeString;  
  8.   
  9.     //初始化UNICODE_STRING字串  
  10.     RtlInitUnicodeString( &logFileUnicodeString,   
  11.         L"\\??\\C:\\1.log");  
  12.     //或者寫成 "\\Device\\HarddiskVolume1\\1.LOG"  
  13.   
  14.     //初始化objectAttributes  
  15.     InitializeObjectAttributes(&objectAttributes,  
  16.                             &logFileUnicodeString,  
  17.                             OBJ_CASE_INSENSITIVE,//對大小寫敏感  
  18.                             NULL,   
  19.                             NULL );  
  20.   
  21.     //新建檔案  
  22.     NTSTATUS ntStatus = ZwCreateFile( &hfile,   
  23.                             GENERIC_READ,  
  24.                             &objectAttributes,   
  25.                             &iostatus,   
  26.                             NULL,  
  27.                             FILE_ATTRIBUTE_NORMAL,   
  28.                             FILE_SHARE_WRITE,  
  29.                             FILE_OPEN,//對檔案開啟,如果不存在則返回錯誤  
  30.                             FILE_SYNCHRONOUS_IO_NONALERT,   
  31.                             NULL,   
  32.                             0 );  
  33.     if ( NT_SUCCESS(ntStatus))  
  34.     {  
  35.         KdPrint(("Open file succussfully!\n"));  
  36.     }else  
  37.     {  
  38.         KdPrint(("Open file  unsuccessfully!\n"));  
  39.     }  
  40.   
  41.     //檔案操作  
  42.     //.......  
  43.   
  44.     //關閉檔案控制代碼  
  45.     ZwClose(hfile);  
  46. }  

需要注意的是當檔案被成功打開後, 一定要記得關閉控制碼, 關閉控制碼使用 ZwClose 內核函式.

檔案的打開 :
除了使用 ZwCreateFile 函式可以打開檔案, DDK 還提供了一個內核函式 ZwOpenFile. 該函式的參數比 ZwCreateFile 的參數簡化, 方便程式設計師打開檔案, 宣告如下 :
- Syntax :
  1. NTSTATUS ZwOpenFile(  
  2.   __out  PHANDLE FileHandle,  
  3.   __in   ACCESS_MASK DesiredAccess,  
  4.   __in   POBJECT_ATTRIBUTES ObjectAttributes,  
  5.   __out  PIO_STATUS_BLOCK IoStatusBlock,  
  6.   __in   ULONG ShareAccess,  
  7.   __in   ULONG OpenOptions  
  8. );  

參數說明 :
* FileHandle : 返回打開檔案控制程式碼.
* DesiredAccess : 打開的權限, 一般為 GENERIC_ALL
* ObjectAttributes : OBJECT_ATTRIBUTES 結構.
* IoStatusBlock : 指向一個結構體的指標, 該結構體指明打開檔案狀態.
* ShareAccess : 共用的權限. 可以是 FILE_SHARE_READ 或者 FILE_SHARE_WRITE
* OpenOptions : 一般為 FILE_SYNCHRONOUS_IO_NONALERT

下面程式碼演示了如何使用 ZwOpenFile 打開檔案 :
- 範例代碼 : 使用函式 ZwOpenFile 打開檔案
  1. #pragma INITCODE  
  2. VOID OpenFileTest2()   
  3. {  
  4.     OBJECT_ATTRIBUTES objectAttributes;  
  5.     IO_STATUS_BLOCK iostatus;  
  6.     HANDLE hfile;  
  7.     UNICODE_STRING logFileUnicodeString;  
  8.   
  9.     //初始化UNICODE_STRING字串  
  10.     RtlInitUnicodeString( &logFileUnicodeString,   
  11.         L"\\??\\C:\\1.log");  
  12.     //或者寫成 "\\Device\\HarddiskVolume1\\1.LOG"  
  13.   
  14.   
  15.     //初始化objectAttributes  
  16.     InitializeObjectAttributes(&objectAttributes,   
  17.                             &logFileUnicodeString,  
  18.                             OBJ_CASE_INSENSITIVE,   
  19.                             NULL,   
  20.                             NULL );  
  21.   
  22.     //新建檔案  
  23.     NTSTATUS ntStatus = ZwOpenFile( &hfile,   
  24.                             GENERIC_ALL,  
  25.                             &objectAttributes,   
  26.                             &iostatus,   
  27.                             FILE_SHARE_READ|FILE_SHARE_WRITE,  
  28.                             FILE_SYNCHRONOUS_IO_NONALERT);  
  29.     if ( NT_SUCCESS(ntStatus))  
  30.     {  
  31.         KdPrint(("Create file succussfully!\n"));  
  32.     }else  
  33.     {  
  34.         KdPrint(("Create file  unsuccessfully!\n"));  
  35.     }  
  36.   
  37.     //檔操作  
  38.     //.......  
  39.   
  40.     //關閉檔案控制代碼  
  41.     ZwClose(hfile);  
  42. }  

獲取或修改檔案屬性 :
獲取和修改檔案屬性, 包括檔案大小, 獲取與修改檔案指標位址, 獲取與修改檔案名, 獲取與修改檔案屬性 (唯讀屬性, 隱藏屬性)等. DDK 提供了內核函式 ZwSetInformtionFile 和ZwQueryInformationFile 函式來進行獲取與修改檔案屬性. 其宣告如下 :
- ZwQueryInformationFile Syntax :
  1. NTSTATUS ZwQueryInformationFile(  
  2.   __in   HANDLE FileHandle,  
  3.   __out  PIO_STATUS_BLOCK IoStatusBlock,  
  4.   __out  PVOID FileInformation,  
  5.   __in   ULONG Length,  
  6.   __in   FILE_INFORMATION_CLASS FileInformationClass  
  7. );  

- ZwSetInformationFile Syntax :
  1. NTSTATUS ZwSetInformationFile(  
  2.   __in   HANDLE FileHandle,  
  3.   __out  PIO_STATUS_BLOCK IoStatusBlock,  
  4.   __in   PVOID FileInformation,  
  5.   __in   ULONG Length,  
  6.   __in   FILE_INFORMATION_CLASS FileInformationClass  
  7. );  

這兩個函式的參數基本相同, 其中 FileInformationClass 指定修改或者查詢的類別.
(1) 當 FileInformationClass 是 FileStandardInformation 時, 輸入與輸出的資料是 FILE_STANDARD_INFORMATION 結構體, 描述檔的基本資訊如下 :
- Syntax :
  1. typedef struct _FILE_STANDARD_INFORMATION {  
  2.   LARGE_INTEGER AllocationSize; // 檔的分配大小 ( The sector or cluster size of the underlying physical device.)  
  3.   LARGE_INTEGER EndOfFile; //距離檔案結尾還有多少位元組  
  4.   ULONG         NumberOfLinks;  // 有多少個連結檔  
  5.   BOOLEAN       DeletePending; // 是否準備刪除  
  6.   BOOLEAN       Directory;  // 是否為目錄  
  7. } FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;  

(2) 當FileInformationClass 是 FileBasicInformation 時, 輸入與輸出的資料是 FILE_BASIC_INFORMATION 結構體, 描述檔資訊如下 :
- Syntax :
  1. typedef struct _FILE_BASIC_INFORMATION {  
  2.   LARGE_INTEGER CreationTime; // 檔新建時間  
  3.   LARGE_INTEGER LastAccessTime;  // 最後存取時間  
  4.   LARGE_INTEGER LastWriteTime; // 最後寫時間  
  5.   LARGE_INTEGER ChangeTime;  // 最後修改時間  
  6.   ULONG         FileAttributes; // 檔案屬性  
  7. } FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;  

其中時間參數是一個 LARGE_INTEGER 的整數, 該整數代表從 1901 年經過多少個 100ns. FileAttributes 描述檔屬性, 而 FILE_ATTRIBUTE_NORMAL 指一般檔, FILE_ATTRIBUTE_DIRECTORY 指目錄, FILE_ATTRIBUTE_READONLY 指該檔唯讀, FILE_ATTRIBUTE_HIDDEN 指該檔維隱含檔, FILE_ATTRIBUTE_SYSTEM 代表系統檔.
(3) 當 FileInformationClass 是 FileNameInformation 時, 輸入與輸出的資料是 FILE_NAME_INFORMATION 結構體, 資訊如下 :
- Syntax :
  1. typedef struct _FILE_NAME_INFORMATION {  
  2.   ULONG FileNameLength; // 檔案名長度  
  3.   WCHAR FileName[1]; // 檔案名  
  4. } FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;  

(4) 當 FileInformationClass 是 FilePositionInformation 時, 輸入和輸出的資料是 FILE_POSITION_INFORMATION 結構體, 資訊如下 :
- Syntax :
  1. typedef struct _FILE_POSITION_INFORMATION {  
  2.   LARGE_INTEGER CurrentByteOffset; // 代表當前檔案指標位址  
  3. } FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;  

下面程式碼演示如何使用 ZwQueryInformationFile 函式查詢, 些改檔案屬性 :
- 範例代碼 : 下面程式碼演示如何使用 ZwQueryInformationFile 函式
  1. #pragma INITCODE  
  2. VOID FileAttributeTest()   
  3. {  
  4.     OBJECT_ATTRIBUTES objectAttributes;  
  5.     IO_STATUS_BLOCK iostatus;  
  6.     HANDLE hfile;  
  7.     UNICODE_STRING logFileUnicodeString;  
  8.   
  9.     //初始化UNICODE_STRING字串  
  10.     RtlInitUnicodeString( &logFileUnicodeString,   
  11.         L"\\??\\C:\\1.log");  
  12.     //或者寫成 "\\Device\\HarddiskVolume1\\1.LOG"  
  13.   
  14.     //初始化objectAttributes  
  15.     InitializeObjectAttributes(&objectAttributes,  
  16.                             &logFileUnicodeString,  
  17.                             OBJ_CASE_INSENSITIVE,//對大小寫敏感  
  18.                             NULL,   
  19.                             NULL );  
  20.   
  21.     //新建檔案  
  22.     NTSTATUS ntStatus = ZwCreateFile( &hfile,   
  23.                             GENERIC_READ,  
  24.                             &objectAttributes,   
  25.                             &iostatus,   
  26.                             NULL,  
  27.                             FILE_ATTRIBUTE_NORMAL,   
  28.                             0,  
  29.                             FILE_OPEN,//對檔案開啟,如果不存在則返回錯誤  
  30.                             FILE_SYNCHRONOUS_IO_NONALERT,   
  31.                             NULL,   
  32.                             0 );  
  33.     if (NT_SUCCESS(ntStatus))  
  34.     {  
  35.         KdPrint(("open file successfully.\n"));  
  36.     }  
  37.   
  38.     FILE_STANDARD_INFORMATION fsi;  
  39.     //讀取檔案長度  
  40.     ntStatus = ZwQueryInformationFile(hfile,  
  41.                                     &iostatus,  
  42.                                     &fsi,  
  43.                                     sizeof(FILE_STANDARD_INFORMATION),  
  44.                                     FileStandardInformation);  
  45.     if (NT_SUCCESS(ntStatus))  
  46.     {  
  47.         KdPrint(("file length:%u\n",fsi.EndOfFile.QuadPart));  
  48.     }  
  49.       
  50.     //修改當前檔案指標  
  51.     FILE_POSITION_INFORMATION fpi;  
  52.     fpi.CurrentByteOffset.QuadPart = 100i64;  
  53.     ntStatus = ZwSetInformationFile(hfile,  
  54.                                 &iostatus,  
  55.                                 &fpi,  
  56.                                 sizeof(FILE_POSITION_INFORMATION),  
  57.                                 FilePositionInformation);  
  58.     if (NT_SUCCESS(ntStatus))  
  59.     {  
  60.         KdPrint(("update the file pointer successfully.\n"));  
  61.     }  
  62.   
  63.     //關閉檔案控制代碼  
  64.     ZwClose(hfile);  
  65. }  

檔案的寫操作 :
DDK 提供了檔案寫入操作的內核函式 ZwWriteFile, 其宣告如下 :
- Syntax :
  1. NTSTATUS ZwWriteFile(  
  2.   __in      HANDLE FileHandle,  
  3.   __in_opt  HANDLE Event,  
  4.   __in_opt  PIO_APC_ROUTINE ApcRoutine,  
  5.   __in_opt  PVOID ApcContext,  
  6.   __out     PIO_STATUS_BLOCK IoStatusBlock,  
  7.   __in      PVOID Buffer,  
  8.   __in      ULONG Length,  
  9.   __in_opt  PLARGE_INTEGER ByteOffset,  
  10.   __in_opt  PULONG Key  
  11. );  

參數說明 :
* FileHandle : 檔案打開的控制碼.
* Event : 一般為 NULL.
* ApcRoutine : 一般為 NULL.
* ApcContext : 一般為 NULL.
* IoStatusBlock : 記錄寫操作的狀態. 其中 IoStatusBlock.Information 記錄了實際寫了多少位元組.
* Buffer : 從這個緩衝區開始往檔案寫.
* Length : 準備寫多少位元組.
* ByteOffset : 從檔的多少偏移位址開始寫.
* Key : 一般為 NULL.

下面程式碼演示了如何對檔案進行寫操作 :
- 範例代碼 : 檔案寫操作
  1. #pragma INITCODE  
  2. VOID WriteFileTest()   
  3. {  
  4.     OBJECT_ATTRIBUTES objectAttributes;  
  5.     IO_STATUS_BLOCK iostatus;  
  6.     HANDLE hfile;  
  7.     UNICODE_STRING logFileUnicodeString;  
  8.   
  9.     //初始化UNICODE_STRING字串  
  10.     RtlInitUnicodeString( &logFileUnicodeString,   
  11.         L"\\??\\C:\\1.log");  
  12.     //或者寫成 "\\Device\\HarddiskVolume1\\1.LOG"  
  13.   
  14.     //初始化objectAttributes  
  15.     InitializeObjectAttributes(&objectAttributes,  
  16.                             &logFileUnicodeString,  
  17.                             OBJ_CASE_INSENSITIVE,//對大小寫敏感  
  18.                             NULL,   
  19.                             NULL );  
  20.   
  21.     //新建檔案  
  22.     NTSTATUS ntStatus = ZwCreateFile( &hfile,   
  23.                             GENERIC_WRITE,  
  24.                             &objectAttributes,   
  25.                             &iostatus,   
  26.                             NULL,  
  27.                             FILE_ATTRIBUTE_NORMAL,   
  28.                             FILE_SHARE_WRITE,  
  29.                             FILE_OPEN_IF,//即使存在該檔案,也新建  
  30.                             FILE_SYNCHRONOUS_IO_NONALERT,   
  31.                             NULL,   
  32.                             0 );  
  33. #define BUFFER_SIZE 1024  
  34.     PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool,BUFFER_SIZE);  
  35.     //建構要填充的資料  
  36.     RtlFillMemory(pBuffer,BUFFER_SIZE,0xAA);  
  37.   
  38.     KdPrint(("The program will write %d bytes\n",BUFFER_SIZE));  
  39.     //寫入檔案  
  40.     ZwWriteFile(hfile,NULL,NULL,NULL,&iostatus,pBuffer,BUFFER_SIZE,NULL,NULL);  
  41.     KdPrint(("The program really wrote %d bytes\n",iostatus.Information));  
  42.   
  43.   
  44.     //建構要填充的資料  
  45.     RtlFillMemory(pBuffer,BUFFER_SIZE,0xBB);  
  46.   
  47.     KdPrint(("The program will append %d bytes\n",BUFFER_SIZE));  
  48.     //追加資料  
  49.     LARGE_INTEGER number;  
  50.     number.QuadPart = 1024i64;//設置檔案指標  
  51.     //對檔案進行附加寫  
  52.     ZwWriteFile(hfile,NULL,NULL,NULL,&iostatus,pBuffer,BUFFER_SIZE,&number,NULL);  
  53.     KdPrint(("The program really appended %d bytes\n",iostatus.Information));  
  54.   
  55.     //關閉檔案控制代碼  
  56.     ZwClose(hfile);  
  57.   
  58.     ExFreePool(pBuffer);  
  59. }  

檔案的讀操作 :
DDK 提供了檔案操作的內核函式 ZwReadFile, 其函式宣告如下 :
- Syntax :
  1. NTSTATUS ZwReadFile(  
  2.   __in      HANDLE FileHandle, // Handle to the file object.  
  3.   __in_opt  HANDLE Event, // Device and intermediate drivers should set this parameter to NULL  
  4.   __in_opt  PIO_APC_ROUTINE ApcRoutine, // Device and intermediate drivers should set this pointer to NULL.  
  5.   __in_opt  PVOID ApcContext, // Device and intermediate drivers should set this pointer to NULL.  
  6.   __out     PIO_STATUS_BLOCK IoStatusBlock, // 記錄了實際讀了多少位元組的狀態.  
  7.   __out     PVOID Buffer, // Pointer to a caller-allocated buffer that receives the data read from the file.  
  8.   __in      ULONG Length, // The size, in bytes, of the buffer pointed to by Buffer.  
  9.   __in_opt  PLARGE_INTEGER ByteOffset,  // 從檔的多少偏移位址開始讀.  
  10.   __in_opt  PULONG Key // Device and intermediate drivers should set this pointer to NULL.  
  11. );  

下面程式碼演示如何在驅動程式中讀取檔案 :
- 範例代碼 : 檔案讀操作
  1. #pragma INITCODE  
  2. VOID ReadFileTest()   
  3. {  
  4.     OBJECT_ATTRIBUTES objectAttributes;  
  5.     IO_STATUS_BLOCK iostatus;  
  6.     HANDLE hfile;  
  7.     UNICODE_STRING logFileUnicodeString;  
  8.   
  9.     //初始化UNICODE_STRING字串  
  10.     RtlInitUnicodeString( &logFileUnicodeString,   
  11.         L"\\??\\C:\\1.log");  
  12.     //或者寫成 "\\Device\\HarddiskVolume1\\1.LOG"  
  13.   
  14.     //初始化objectAttributes  
  15.     InitializeObjectAttributes(&objectAttributes,  
  16.                             &logFileUnicodeString,  
  17.                             OBJ_CASE_INSENSITIVE,//對大小寫敏感  
  18.                             NULL,   
  19.                             NULL );  
  20.   
  21.     //新建檔案  
  22.     NTSTATUS ntStatus = ZwCreateFile( &hfile,   
  23.                             GENERIC_READ,  
  24.                             &objectAttributes,   
  25.                             &iostatus,   
  26.                             NULL,  
  27.                             FILE_ATTRIBUTE_NORMAL,   
  28.                             FILE_SHARE_READ,  
  29.                             FILE_OPEN,//即使存在該檔案,也新建  
  30.                             FILE_SYNCHRONOUS_IO_NONALERT,   
  31.                             NULL,   
  32.                             0 );  
  33.   
  34.     if (!NT_SUCCESS(ntStatus))  
  35.     {  
  36.         KdPrint(("The file is not exist!\n"));  
  37.         return;  
  38.     }  
  39.   
  40.     FILE_STANDARD_INFORMATION fsi;  
  41.     //讀取檔案長度  
  42.     ntStatus = ZwQueryInformationFile(hfile,  
  43.                                     &iostatus,  
  44.                                     &fsi,  
  45.                                     sizeof(FILE_STANDARD_INFORMATION),  
  46.                                     FileStandardInformation);  
  47.   
  48.     KdPrint(("The program want to read %d bytes\n",fsi.EndOfFile.QuadPart));  
  49.   
  50.     //為讀取的檔案分配緩衝區  
  51.     PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool,  
  52.                                 (LONG)fsi.EndOfFile.QuadPart);  
  53.   
  54.     //讀取檔案  
  55.     ZwReadFile(hfile,NULL,  
  56.                 NULL,NULL,  
  57.                 &iostatus,  
  58.                 pBuffer,  
  59.                 (LONG)fsi.EndOfFile.QuadPart,  
  60.                 NULL,NULL);  
  61.     KdPrint(("The program really read %d bytes\n",iostatus.Information));  
  62.     //關閉檔案控制代碼  
  63.     ZwClose(hfile);  
  64.   
  65.     //釋放緩衝區  
  66.     ExFreePool(pBuffer);  
  67. }  

補充說明 :
MSDN : CreateFile Function
Creates or opens a file or I/O device. The most commonly used I/O devices are as follows: file, file stream, directory, physical disk, volume, console buffer, tape drive, communications resource, mailslot, and pipe. The function returns a handle that can be used to access the file or device for various types of I/O depending on the file or device and the flags and attributes specified.

如何從核心模式裝置驅動程式中開啟檔案,以及如何從讀取或寫入至檔案 :
本文將告訴您如何從核心模式裝置驅動程式開啟磁碟檔案,以及如何讀取或寫入檔案
This message was edited 13 times. Last update was at 23/12/2010 11:37:39

沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...