Membuat Permintaan IOCTL di Driver

Driver kelas atau driver tingkat lebih tinggi lainnya dapat mengalokasikan IRP untuk permintaan kontrol I/O dan mengirimkannya ke driver yang lebih rendah berikutnya sebagai berikut:

  1. Alokasikan atau gunakan kembali paket permintaan I/O (IRP) dengan kode fungsi utama IRP_MJ_DEVICE_CONTROL atau IRP_MJ_INTERNAL_DEVICE_CONTROL. Anda dapat menggunakan rutinitas IoBuildDeviceIoControlRequest untuk secara khusus mengalokasikan IOCTL IRP. Anda juga dapat menggunakan rutinitas pembuatan dan inisialisasi IRP tujuan umum, seperti IoAllocateIrp, IoReuseIrp, atau IoInitializeIrp. Untuk informasi selengkapnya tentang alokasi IRP, lihat Membuat IRP untuk Driver Lower-Level.

  2. Siapkan lokasi tumpukan I/O driver yang lebih rendah untuk IRP dengan kode IOCTL_XXX dan parameter yang sesuai.

  3. Jika permintaan IOCTL harus diselesaikan secara asinkron, panggil rutinitas KeInitializeEvent untuk menginisialisasi objek peristiwa sebagai peristiwa pemberitahuan. Driver menggunakan kejadian ini untuk menunggu operasi I/O selesai.

  4. Panggil IoSetCompletionRoutine dengan IRP sehingga driver atas dapat menyediakan rutinitas IoCompletion , jika perlu, untuk melakukan hal berikut:

    • Tentukan bagaimana driver yang lebih rendah menangani permintaan tertentu.

    • Gunakan kembali IRP untuk mengirim permintaan lain atau membuang IRP yang dibuat driver, setelah driver yang lebih rendah menyelesaikan operasi yang diminta. Driver tidak dapat menggunakan kembali IRP yang dibuat IoBuildDeviceIoControlRequest . Untuk informasi selengkapnya, lihat Menggunakan kembali IRP.

  5. Hubungi IoCallDriver untuk meneruskan permintaan ke driver yang lebih rendah.

  6. Jika IoCallDriver mengembalikan STATUS_PENDING, panggil rutinitas KeWaitForSingleObject untuk menempatkan utas saat ini ke dalam status tunggu. Driver mengatur parameter Objek rutin ke alamat objek peristiwa yang diinisialisasi dalam panggilan ke KeInitializeEvent.

    Catatan Jika driver memanggil KeWaitForSingleObject dengan parameter Timeout-nya diatur ke NULL atau ke alamat variabel yang berisi nilai bukan nol, driver harus berjalan di IRQL <= APC_LEVEL dalam konteks rangkaian nonarbitrer. Jika tidak, driver harus berjalan di IRQL <= DISPATCH_LEVEL.

Peristiwa ini disinyalir oleh rutinitas IoCompletion-nya ketika permintaan IOCTL telah selesai. Setelah peristiwa disinyalkan, utas melanjutkan eksekusi.

Penting Jika driver mengalokasikan objek peristiwa sebagai variabel lokal pada tumpukan, driver harus memanggil KeWaitForSingleObject dengan parameter WaitMode-nya diatur ke KernelMode. Nilai parameter ini mencegah tumpukan di-paged out.

Untuk menghindari masalah sinkronisasi dan kemungkinan pelanggaran akses, parameter untuk kode kontrol I/O jarang menyertakan pointer yang disematkan. Kecuali untuk permintaan SCSI tertentu, buffer di Irp-AssociatedIrp>. SystemBuffer, di Irp-MdlAddress>, dan di Parameter. DeviceIoControl. Type3InputBuffer di lokasi tumpukan I/O driver tidak berisi pointer ke buffer data lain, juga tidak berisi struktur yang berisi penunjuk untuk kode kontrol I/O yang ditentukan sistem. Untuk informasi selengkapnya tentang bagaimana buffer data digunakan dengan IRP yang berisi kode kontrol I/O, lihat Deskripsi Buffer untuk Kode Kontrol I/O.

Namun demikian, sepasang driver kelas/port yang menentukan kode kontrol I/O internal dapat meneruskan penunjuk tersemat ke memori yang dialokasikan driver dari driver tingkat yang lebih tinggi ke driver tingkat bawah. Sepasang driver kelas/port semacam itu bertanggung jawab untuk memastikan bahwa hal berikut ini benar:

  • Hanya satu driver pada satu waktu yang dapat mengakses data.

  • Buffer data privat dapat diakses dalam konteks utas arbitrer oleh driver port.

Driver tampilan dapat memanggil fungsi GDI EngDeviceIoControl untuk mengirim permintaan kontrol I/O khusus perangkat yang ditentukan secara privat, serta permintaan kontrol I/O publik yang ditentukan sistem, melalui driver port video sistem ke driver miniport video khusus adaptor yang sesuai.

Setiap komponen mode pengguna dari paket driver dapat memanggil DeviceIoControl untuk mengirim permintaan kontrol I/O ke tumpukan driver. Manajer I/O membuat permintaan IRP_MJ_DEVICE_CONTROL dan mengirimkannya ke driver tingkat tertinggi.