Menentukan Kode Kontrol I/O
Saat menentukan IOCTL baru, penting untuk mengingat aturan berikut:
- Jika IOCTL baru akan tersedia untuk komponen perangkat lunak mode pengguna, IOCTL harus digunakan dengan permintaan IRP_MJ_DEVICE_CONTROL . Komponen mode pengguna mengirim permintaan IRP_MJ_DEVICE_CONTROL dengan memanggil DeviceIoControl, yang merupakan fungsi Win32.
- Jika IOCTL baru hanya akan tersedia untuk komponen driver mode kernel, IOCTL harus digunakan dengan permintaan IRP_MJ_INTERNAL_DEVICE_CONTROL . Komponen mode kernel membuat permintaan IRP_MJ_INTERNAL_DEVICE_CONTROL dengan memanggil IoBuildDeviceIoControlRequest. Untuk informasi selengkapnya, lihat Membuat Permintaan IOCTL di Driver.
Kode kontrol I/O adalah nilai 32-bit yang terdiri dari beberapa bidang. Gambar berikut mengilustrasikan tata letak kode kontrol I/O.
Gunakan makro CTL_CODE yang disediakan sistem, yang didefinisikan dalam Wdm.h dan Ntddk.h, untuk menentukan kode kontrol I/O baru. Definisi kode IOCTL baru, baik yang dimaksudkan untuk digunakan dengan permintaan IRP_MJ_DEVICE_CONTROL atau IRP_MJ_INTERNAL_DEVICE_CONTROL , menggunakan format berikut:
#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)
Pilih nama konstanta deskriptif untuk IOCTL, dari formulir IOCTL_Device_Function, di mana Perangkat menunjukkan jenis perangkat dan Fungsi menunjukkan operasi. Contoh nama konstanta adalah IOCTL_VIDEO_ENABLE_CURSOR.
Berikan parameter berikut ke makro CTL_CODE :
DeviceType
Mengidentifikasi jenis perangkat. Nilai ini harus cocok dengan nilai yang diatur dalam anggota DeviceType dari struktur DEVICE_OBJECT driver. (Lihat Menentukan jenis perangkat). Nilai kurang dari 0x8000 disediakan untuk Microsoft. Nilai 0x8000 dan yang lebih tinggi dapat digunakan oleh vendor. Perhatikan bahwa nilai yang ditetapkan vendor menetapkan bit Umum .
FunctionCode
Mengidentifikasi fungsi yang akan dilakukan oleh driver. Nilai kurang dari 0x800 disediakan untuk Microsoft. Nilai 0x800 dan yang lebih tinggi dapat digunakan oleh vendor. Perhatikan bahwa nilai yang ditetapkan vendor mengatur bit Kustom .
TransferType
Menunjukkan bagaimana sistem akan meneruskan data antara pemanggil DeviceIoControl (atau IoBuildDeviceIoControlRequest) dan driver yang menangani IRP.
Gunakan salah satu konstanta yang ditentukan sistem berikut:
METHOD_BUFFERED
Menentukan metode I/O yang di-buffer , yang biasanya digunakan untuk mentransfer sejumlah kecil data per permintaan. Sebagian besar kode kontrol I/O untuk perangkat dan driver perantara menggunakan nilai TransferType ini.
Untuk informasi tentang bagaimana sistem menentukan buffer data untuk kode kontrol I/O METHOD_BUFFERED, lihat Deskripsi Buffer untuk Kode Kontrol I/O.
Untuk informasi selengkapnya tentang I/O yang di-buffer, lihat Menggunakan I/O buffered.
METHOD_IN_DIRECT atau METHOD_OUT_DIRECT
Menentukan metode I/O langsung , yang biasanya digunakan untuk membaca atau menulis data dalam jumlah besar, menggunakan DMA atau PIO, yang harus ditransfer dengan cepat.
Tentukan METHOD_IN_DIRECT jika pemanggil DeviceIoControl atau IoBuildDeviceIoControlRequest akan meneruskan data ke driver.
Tentukan METHOD_OUT_DIRECT jika pemanggil DeviceIoControl atau IoBuildDeviceIoControlRequest akan menerima data dari driver.
Untuk informasi tentang bagaimana sistem menentukan buffer data untuk kode kontrol I/O METHOD_IN_DIRECT dan METHOD_OUT_DIRECT, lihat Deskripsi Buffer untuk Kode Kontrol I/O.
Untuk informasi selengkapnya tentang I/O langsung, lihat Menggunakan I/O Langsung.
METHOD_NEITHER
Menentukan tidak ada buffer atau I/O langsung. Manajer I/O tidak menyediakan buffer sistem atau MDL apa pun. IRP menyediakan alamat virtual mode pengguna dari buffer input dan output yang ditentukan ke DeviceIoControl atau IoBuildDeviceIoControlRequest, tanpa memvalidasi atau memetakannya.
Untuk informasi tentang bagaimana sistem menentukan buffer data untuk kode kontrol I/O METHOD_NEITHER, lihat Deskripsi Buffer untuk Kode Kontrol I/O.
Metode ini hanya dapat digunakan jika driver dapat dijamin berjalan dalam konteks utas yang berasal dari permintaan kontrol I/O. Hanya driver mode kernel tingkat tertinggi yang dijamin memenuhi kondisi ini, jadi METHOD_NEITHER jarang digunakan untuk kode kontrol I/O yang diteruskan ke driver perangkat tingkat rendah.
Dengan metode ini, driver tingkat tertinggi harus menentukan apakah akan menyiapkan akses buffer atau langsung ke data pengguna pada penerimaan permintaan, mungkin harus mengunci buffer pengguna, dan harus membungkus aksesnya ke buffer pengguna dalam handler pengecualian terstruktur (lihat Menangani Pengecualian). Jika tidak, pemanggil mode pengguna asal dapat mengubah data yang di-buffer sebelum driver dapat menggunakannya, atau pemanggil dapat ditukar sama seperti driver mengakses buffer pengguna.
Untuk informasi selengkapnya, lihat Menggunakan Buffered maupun I/O Langsung.
RequiredAccess
Menunjukkan jenis akses yang harus diminta pemanggil saat membuka objek file yang mewakili perangkat (lihat IRP_MJ_CREATE). Manajer I/O akan membuat RUNP dan memanggil driver dengan kode kontrol I/O tertentu hanya jika pemanggil telah meminta hak akses yang ditentukan.
RequiredAccess ditentukan dengan menggunakan konstanta yang ditentukan sistem berikut:
FILE_ANY_ACCESS
Manajer I/O mengirimkan IRP untuk pemanggil apa pun yang memiliki handel ke objek file yang mewakili objek perangkat target.
FILE_READ_DATA
Manajer I/O mengirimkan IRP hanya untuk penelepon dengan hak akses baca, memungkinkan driver perangkat yang mendasar mentransfer data dari perangkat ke memori sistem.
FILE_WRITE_DATA
Manajer I/O mengirimkan IRP hanya untuk penelepon dengan hak akses tulis, memungkinkan driver perangkat yang mendasar mentransfer data dari memori sistem ke perangkatnya.
FILE_READ_DATA dan FILE_WRITE_DATA dapat menjadi ORed bersama-sama jika pemanggil harus memiliki hak akses baca dan tulis.
Beberapa kode kontrol I/O yang ditentukan sistem memiliki nilai RequiredAccess FILE_ANY_ACCESS, yang memungkinkan pemanggil untuk mengirim IOCTL tertentu terlepas dari akses yang diberikan ke perangkat. Contohnya termasuk kode kontrol I/O yang dikirim ke driver perangkat eksklusif.
Kode kontrol I/O lain yang ditentukan sistem mengharuskan pemanggil memiliki hak akses baca, hak akses tulis, atau keduanya. Misalnya, definisi kode kontrol I/O publik berikut IOCTL_DISK_SET_PARTITION_INFO menunjukkan bahwa permintaan I/O ini dapat dikirim ke driver hanya jika pemanggil memiliki hak akses baca dan tulis:
#define IOCTL_DISK_SET_PARTITION_INFO\
CTL_CODE(IOCTL_DISK_BASE, 0x008, METHOD_BUFFERED,\
FILE_READ_DATA | FILE_WRITE_DATA)
Catatan
Sebelum menentukan FILE_ANY_ACCESS untuk kode IOCTL baru, Anda harus benar-benar yakin bahwa memungkinkan akses tidak terbatas ke perangkat Anda tidak membuat jalur yang mungkin bagi pengguna jahat untuk membahayakan sistem.
Driver dapat menggunakan IoValidateDeviceIoControlAccess untuk melakukan pemeriksaan akses yang lebih ketat daripada yang disediakan oleh bit RequiredAccess IOCTL.
Makro berguna lainnya
Makro berikut berguna untuk mengekstrak bidang DeviceType 16-bit dan TransferType 2-bit dari kode IOCTL:
#define DEVICE_TYPE_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0xffff0000)) >> 16)
#define METHOD_FROM_CTL_CODE(ctrlCode) ((ULONG)(ctrlCode & 3))
Makro ini didefinisikan dalam Wdm.h dan Ntddk.h.