カーネル モードのデバイス ドライバからファイルを開く方法、およびファイルに対して読み取りまたは書き込みを行う方法

適用対象: Windows

はじめに


この資料では、カーネル モードのデバイス ドライバからディスク ファイルを開く方法、およびファイルに対して読み取りまたは書き込みを行う方法について説明します。

詳細情報


オブジェクト名によるファイルの参照

カーネル モードのデバイス ドライバでは、オブジェクト名でファイルを参照します。 この名前は、\DosDevices とファイルの完全なパスを組み合わせたものです。 たとえば、C:\Windows\Example.txt ファイルのオブジェクト名は、\DosDevices\C:\Windows\Example.txt です。 その後、InitializeObjectAttributes 関数を呼び出すことにより、オブジェクト名を OBJECT_ATTRIBUTES 構造体でカプセル化します。

注 : 早い段階でデバイス ドライバが読み込まれた場合、\DosDevices 名前空間がまだ存在していないことがあります。 その場合、デバイス ドライバから\DosDevices 名前空間にアクセスできません。これは、公開されているドライブ文字がないためです。 ファイル システムで確実に利用できる唯一の部分は、\SystemRoot名前空間です。 \SystemRoot 名前空間は、オペレーティング システムがインストールされているフォルダにマッピングされています。 たとえば、このフォルダがC:\WindowsまたはD:\Winntかもしれません。

次のコード例は、オブジェクト名でファイルを参照する方法を示しています。
    UNICODE_STRING     uniName;
OBJECT_ATTRIBUTES objAttr;

RtlInitUnicodeString(&uniName, L"\\DosDevices\\C:\\WINDOWS\\example.txt"); // or L"\\SystemRoot\\example.txt"
InitializeObjectAttributes(&objAttr, &uniName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, NULL);

ファイル ハンドルの取得

ファイル ハンドルを取得するには、OBJECT_ATTRIBUTES 構造体を ZwCreateFile 関数に渡します。 DesiredAccess パラメータは、目的に応じて GENERIC_READGENERIC_WRITE、または GENERIC_ALL に設定することができます。CreateOptions パラメータを FILE_SYNCHRONOUS_IO_NONALERT または FILE_SYNCHRONOUS_IO_ALERT に設定した場合、ファイル システムにより、現在のファイル位置オフセットが記録されます。 したがって、後でファイルを順番に読み書きできます。 また、ファイル内の任意の場所にアクセスすることもできます。

次のコード例は、ファイル ハンドルの取得方法を示しています。
    HANDLE   handle;
NTSTATUS ntstatus;
IO_STATUS_BLOCK ioStatusBlock;

// Do not try to perform any file operations at higher IRQL levels.
// Instead, you may use a work item or a system worker thread to perform file operations.

if(KeGetCurrentIrql() != PASSIVE_LEVEL)
return STATUS_INVALID_DEVICE_STATE;

ntstatus = ZwCreateFile(&handle,
GENERIC_WRITE,
&objAttr, &ioStatusBlock, NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0);

ファイルに対する読み取りまたは書き込み

ファイル ハンドルを取得したら、ZwReadFile 関数または ZwWriteFile 関数を呼び出すことができます。 ファイルの変更が完了したら、ZwClose 関数を使用してハンドルを閉じます。

次のコード例は、ファイルへの書き込み方法を示しています。
    #define  BUFFER_SIZE 30
CHAR buffer[BUFFER_SIZE];
size_t cb;

if(NT_SUCCESS(ntstatus)) {
ntstatus = RtlStringCbPrintfA(buffer, sizeof(buffer), "This is %d test\r\n", 0x0);
if(NT_SUCCESS(ntstatus)) {
ntstatus = RtlStringCbLengthA(buffer, sizeof(buffer), &cb);
if(NT_SUCCESS(ntstatus)) {
ntstatus = ZwWriteFile(handle, NULL, NULL, NULL, &ioStatusBlock,
buffer, cb, NULL, NULL);
}
}
ZwClose(handle);
}
次のコード例は、ファイルからの読み取り方法を示しています。
    LARGE_INTEGER      byteOffset;

ntstatus = ZwCreateFile(&handle,
GENERIC_READ,
&objAttr, &ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0);
if(NT_SUCCESS(ntstatus)) {
byteOffset.LowPart = byteOffset.HighPart = 0;
ntstatus = ZwReadFile(handle, NULL, NULL, NULL, &ioStatusBlock,
buffer, BUFFER_SIZE, &byteOffset, NULL);
if(NT_SUCCESS(ntstatus)) {
buffer[BUFFER_SIZE-1] = '\0';
DbgPrint("%s\n", buffer);
}
ZwClose(handle);
}

関連情報


ドライバでのファイルの使用方法の詳細については、Windows Driver Development Kit の「Using Files In A Driver」を参照してください。

Windows Driver Development Kit の詳細については、次のマイクロソフト Web サイトを参照してください。