Bagikan melalui


Menentukan kode kontrol I/O

Artikel ini menjelaskan cara membuat kode kontrol I/O unik (IOCTL). IOCTL dapat berupa:

  • IOCTL publik, yang biasanya ditentukan sistem dan didokumenkan oleh Microsoft.
  • IOCTL privat, yang biasanya dimaksudkan untuk digunakan secara eksklusif oleh komponen perangkat lunak vendor untuk berkomunikasi satu sama lain. Mereka biasanya didefinisikan dalam file header vendor dan tidak didokumenkan oleh Microsoft.

Tata letak IOCTL

IOCTL adalah nilai 32-bit yang terdiri dari beberapa bidang. Gambar berikut mengilustrasikan tata letak bit per bit untuk IOCTL.

Diagram yang mengilustrasikan tata letak bitwise dari kode kontrol i/o 32-bit.

Setiap bidang di IOCTL memiliki tujuan tertentu, seperti yang dijelaskan dalam tabel berikut:

Bidang Bit-bit dalam IOCTL Deskripsi
Umum 31 Vendor harus mengatur bit ini ketika mereka menggunakan nilai yang ditetapkan vendor untuk DeviceType.
DeviceType 16-30 Mengidentifikasi jenis perangkat. Nilai ini harus cocok dengan nilai yang ditetapkan dalam anggota DeviceType dari struktur DEVICE_OBJECT driver. Vendor harus menggunakan nilai dari 32768 hingga 65535 (0x8000 melalui 0xffff), dan harus mengatur Bit umum . Nilai 0 hingga 32767 (0x0000 hingga 0x7fff) dikhususkan untuk Microsoft. Untuk informasi selengkapnya, lihat Menentukan Jenis Perangkat.
Akses 14-15 Menunjukkan jenis akses yang harus diminta pemanggil saat membuka objek file yang mewakili perangkat (lihat IRP_MJ_CREATE). Manajer I/O akan membuat IRP dan memanggil driver dengan IOCTL tertentu hanya jika pemanggil meminta hak akses tertentu. Bidang ini ditentukan menggunakan konstanta yang ditentukan sistem berikut: FILE_ANY_ACCESS, FILE_READ_DATA, dan FILE_WRITE_DATA.
Khusus 13 Saat diatur, menunjukkan bahwa IOCTL adalah IOCTL yang didefinisikan oleh vendor.
Fungsi 2-12 Kode unik untuk driver yang mengidentifikasi fungsi yang harus dilakukan. Untuk IOCTL yang dibuat vendor, gunakan nilai 2048 hingga 4095 (0x800 hingga 0xfff) dan atur Bit kustom . Nilai yang kurang dari 2048 (0x000 hingga 0x7ff) dicadangkan untuk Microsoft.
Metode 0-1 Menunjukkan bagaimana sistem meneruskan data antara pemanggil DeviceIoControl (atau IoBuildDeviceIoControlRequest) dan driver yang menangani IRP. Untuk informasi selengkapnya, lihat Panduan untuk mengatur bit Metode.

Makro untuk menentukan kode kontrol I/O

Gunakan makro CTL_CODE yang disediakan sistem untuk menentukan kode kontrol I/O baru. Makro ini didefinisikan dalam devioctl.h sebagai berikut:

#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)

Lihat bagian sebelumnya untuk deskripsi DeviceType, Function, Method, dan Access.

Ingatlah aturan berikut saat 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. Misalnya, konstanta IOCTL_VIDEO_ENABLE_CURSOR yang disediakan sistem menggunakan "VIDEO" untuk Perangkat dan "ENABLE_CURSOR" untuk Fungsi.

Panduan untuk mengatur bit Access

Saat menentukan IOCTL baru, Anda harus memilih nilai untuk bidang Bit akses yang menunjukkan jenis akses yang harus diminta pemanggil saat membuka objek file yang mewakili perangkat. Manajer I/O akan membuat IRP dan memanggil driver dengan IOCTL tertentu hanya jika pemanggil meminta hak akses yang ditentukan.

Akses ditentukan dengan menggunakan konstanta yang ditentukan sistem berikut:

  • Akses_File_Apa_Saja

    Manajer I/O mengirimkan IRP untuk setiap pemanggil yang memiliki handle ke objek file yang mewakili objek perangkat target. 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 berbahaya untuk membahayakan sistem.

  • MEMBACA_DATA_FILE

    Manajer I/O mengirimkan IRP hanya untuk penelepon dengan hak akses baca, yang memungkinkan driver perangkat yang mendasar mentransfer data dari perangkat ke memori sistem.

  • TULIS_DATA_BERKAS

    Manajer I/O mengirimkan IRP hanya untuk penelepon dengan hak akses tulis, memungkinkan driver perangkat yang mendasar untuk mentransfer data dari memori sistem ke perangkat tersebut.

FILE_READ_DATA dan FILE_WRITE_DATA dapat digabungkan dengan OR apabila pemanggil memerlukan hak akses baca dan tulis.

Beberapa kode kontrol I/O yang ditentukan sistem memiliki nilai Akses 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 publik berikut IOCTL_DISK_SET_PARTITION_INFO IOCTL 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)

Driver dapat menggunakan IoValidateDeviceIoControlAccess untuk melakukan pemeriksaan akses yang lebih ketat daripada yang disediakan oleh bit Akses IOCTL.

Panduan untuk mengatur bit Metode

Saat menentukan IOCTL baru, Anda harus memilih nilai untuk bidang Bit metode yang menunjukkan bagaimana sistem meneruskan data antara pemanggil DeviceIoControl (atau IoBuildDeviceIoControlRequest) dan driver yang menangani IRP.

Gunakan salah satu konstanta yang ditentukan sistem berikut untuk mengatur bidang Metode .

  • METODE_BUFFERED

    Menentukan metode I/O buffer, yang biasanya digunakan untuk mentransfer sejumlah kecil data per permintaan. Sebagian besar kode kontrol I/O untuk perangkat dan driver perantara menggunakan nilai 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 ter-buffer, lihat Menggunakan I/O ter-buffer.

  • 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.

  • METODE_TIDAK_SATU_PUN

    Menentukan metode I/O tidak di-buffer atau 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 untuk 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 dijamin berjalan dalam konteks utas yang berasal dari permintaan kontrol I/O. Hanya driver mode kernel tingkat tertinggi yang dijamin untuk memenuhi kondisi ini, jadi METHOD_NEITHER jarang digunakan untuk IOCTL yang diteruskan ke driver perangkat tingkat rendah.

    Dengan metode ini, driver tingkat tertinggi:

    • Harus menentukan apakah akan menyiapkan akses yang dibuffer atau langsung ke data pengguna pada penerimaan permintaan.
    • Mungkin harus mengunci buffer pengguna.
    • Harus membungkus aksesnya ke buffer pengguna dalam handler pengecualian terstruktur (lihat Menangani Pengecualian).

    Jika tidak, pemanggil mode pengguna yang asli dapat mengubah data buffer sebelum driver dapat menggunakannya, atau pemanggil dapat dipindahkan dari memori tepat saat driver mengakses buffer pengguna.

    Untuk informasi selengkapnya, lihat Menggunakan I/O yang Tidak Buffered maupun Langsung.

Makro berguna lainnya

Makro berikut berguna untuk mengekstrak bidang DeviceType 16-bit dan Metode 2-bit dari 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.