2009年10月9日 星期五

DDK 檔案操作

//新建及打開檔案
//
ZwCreateFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength
);

typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR
PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;

#pragma INITCODE
VOID CreateFileTest()
{
//新建檔案範例
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK iostatus;
HANDLE hfile;
UNICODE_STRING logFileUnicodeString;

//初始化UNICODE_STRING字串
RtlInitUnicodeString( &logFileUnicodeString,
L"\\??\\C:\\test.log");
//或者寫成 "\\Device\\HarddiskVolume1\\test.LOG"


//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
&logFileUnicodeString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );

//新建檔案
NTSTATUS ntStatus = ZwCreateFile( &hfile,
GENERIC_WRITE,
&objectAttributes,
&iostatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF, //如果要讀取檔案,改成FILE_OPEN,如果不存在則返回錯誤
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0 );
if ( NT_SUCCESS(ntStatus))
{
KdPrint(("Create file succussfully!\n"));
}else
{
KdPrint(("Create file unsuccessfully!\n"));
}

//關閉檔案控制代碼
ZwClose(hfile);
}

===========================================================
可以使用較簡單的方式開啟檔案
ZwOpenFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG ShareAccess,
IN ULONG OpenOptions
);
===========================================================
檔案屬性讀取及設定
ZwQueryInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);

ZwSetInformationFile(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);

FileInformationClass用來指定或查詢的類別
ex:FilePositionInformation,FileBasicInformation...

範例
FILE_STANDARD_INFORMATION fsi;
//讀取檔案長度
ntStatus = ZwQueryInformationFile(hfile,
&iostatus,
&fsi,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation);
if (NT_SUCCESS(ntStatus))
{
KdPrint(("file length:%u\n",fsi.EndOfFile.QuadPart));
}

//修改當前檔案指標
FILE_POSITION_INFORMATION fpi;
fpi.CurrentByteOffset.QuadPart = 100i64;
ntStatus = ZwSetInformationFile(hfile,
&iostatus,
&fpi,
sizeof(FILE_POSITION_INFORMATION),
FilePositionInformation);

===========================================================
FILE讀寫
ZwWriteFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL
);

ZwReadFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL
);

範例:
寫檔

OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK iostatus;
HANDLE hfile;
UNICODE_STRING logFileUnicodeString;

//初始化UNICODE_STRING字串
RtlInitUnicodeString( &logFileUnicodeString,
L"\\??\\C:\\test.log");

//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
&logFileUnicodeString,
OBJ_CASE_INSENSITIVE,//對大小寫敏感
NULL,
NULL );

//新建檔案
NTSTATUS ntStatus = ZwCreateFile( &hfile,
GENERIC_WRITE,
&objectAttributes,
&iostatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_WRITE,
FILE_OPEN_IF,//即使存在該檔案,也新建
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0 );
#define BUFFER_SIZE 1024
PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool,BUFFER_SIZE);
//建構要填充的資料
RtlFillMemory(pBuffer,BUFFER_SIZE,0xAA);

KdPrint(("The program will write %d bytes\n",BUFFER_SIZE));
//寫入檔案
ZwWriteFile(hfile,NULL,NULL,NULL,&iostatus,pBuffer,BUFFER_SIZE,NULL,NULL);
KdPrint(("The program really wrote %d bytes\n",iostatus.Information));


//建構要填充的資料
RtlFillMemory(pBuffer,BUFFER_SIZE,0xBB);

KdPrint(("The program will append %d bytes\n",BUFFER_SIZE));
//追加資料
LARGE_INTEGER number;
number.QuadPart = 1024i64;//設置檔案指標
//對檔案進行附加寫
ZwWriteFile(hfile,NULL,NULL,NULL,&iostatus,pBuffer,BUFFER_SIZE,&number,NULL);
KdPrint(("The program really appended %d bytes\n",iostatus.Information));

//關閉檔案控制代碼
ZwClose(hfile);

ExFreePool(pBuffer);

讀檔與寫檔類似:
FILE_STANDARD_INFORMATION fsi;
//讀取檔案長度
ntStatus = ZwQueryInformationFile(hfile,
&iostatus,
&fsi,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation);

KdPrint(("The program want to read %d bytes\n",fsi.EndOfFile.QuadPart));

//為讀取的檔案分配緩衝區
PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool,
(LONG)fsi.EndOfFile.QuadPart);

//讀取檔案
ZwReadFile(hfile,NULL,
NULL,NULL,
&iostatus,
pBuffer,
(LONG)fsi.EndOfFile.QuadPart,
NULL,NULL);
KdPrint(("The program really read %d bytes\n",iostatus.Information));

沒有留言 :