Sdílet prostřednictvím


Definování kódů ovládacích prvků vstupně-výstupních operací

Při definování nových IOCTLs je důležité pamatovat na následující pravidla:

  • Pokud bude nová IOCTL k dispozici softwarovým komponentám v uživatelském režimu, musí být tato IOCTL použita s požadavky IRP_MJ_DEVICE_CONTROL. Komponenty uživatelského režimu odesílají požadavky IRP_MJ_DEVICE_CONTROL voláním DeviceIoControl, což je funkce Win32.
  • Pokud bude nová hodnota IOCTL k dispozici pouze pro součásti ovladače v režimu jádra, musí být hodnota IOCTL použita s požadavky IRP_MJ_INTERNAL_DEVICE_CONTROL . Komponenty režimu jádra vytvářejí požadavky IRP_MJ_INTERNAL_DEVICE_CONTROL voláním IoBuildDeviceIoControlRequest. Další informace naleznete v tématu Vytváření žádostí IOCTL v ovladačích.

Kód ovládacího prvku vstupně-výstupních operací je 32bitová hodnota, která se skládá z několika polí. Následující obrázek znázorňuje rozložení kódů ovládacích prvků vstupně-výstupních operací.

diagram znázorňující rozložení kódu ovládacích prvků vstupně-výstupních operací

Pomocí systémového CTL_CODE makra, které je definováno v wdm.h a Ntddk.h, definujte nové vstupně-výstupní řídicí kódy. Definice nového kódu IOCTL, ať už je určená pro IRP_MJ_DEVICE_CONTROL nebo IRP_MJ_INTERNAL_DEVICE_CONTROL požadavky, používá následující formát:

#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)

Zvolte popisný název konstanty pro hodnotu IOCTL formuláře IOCTL_Device_Function, kde Zařízení označuje typ zařízení a funkce označuje operaci. Příklad názvu konstanty je IOCTL_VIDEO_ENABLE_CURSOR.

Do CTL_CODE makra zadejte následující parametry:

DeviceType
Identifikuje typ zařízení. Tato hodnota se musí shodovat s hodnotou nastavenou v členu DeviceType struktury DEVICE_OBJECT ovladače. (Viz Určení typů zařízení). Hodnoty menší než 0x8000 jsou vyhrazené pro Microsoft. Hodnoty 0x8000 a vyšší můžou používat dodavatelé. Všimněte si, že hodnoty přiřazené dodavatelem nastavily Common bit.

FunctionCode
Identifikuje funkci, kterou má ovladač provést. Hodnoty menší než 0x800 jsou vyhrazené pro Microsoft. Hodnoty 0x800 a vyšší můžou používat dodavatelé. Všimněte si, že hodnoty přiřazené dodavatelem nastavují Custom bit.

Typ přenosu
Určuje, jak bude systém předávat data mezi volajícím DeviceIoControl (nebo IoBuildDeviceIoControlRequest) a ovladačem, který zpracovává IRP.

Použijte jednu z následujících systémově definovaných konstant:

METHOD_BUFFERED
Určuje metodu vyrovnaného I/O, která se obvykle používá pro přenos malých objemů dat na každou žádost. Většina kódů ovládacích prvků vstupně-výstupních operací pro zařízení a zprostředkující ovladače používá tuto hodnotu TransferType .

Informace o tom, jak systém určuje vyrovnávací paměti dat pro METHOD_BUFFERED vstupně-výstupní řídicí kódy, naleznete v tématu Popisy vyrovnávací paměti pro vstupně-výstupní řídicí kódy.

Další informace o vstupně-výstupních operacích s vyrovnávací pamětí najdete v tématu Použití vstupně-výstupních operací ve vyrovnávací paměti.

METHOD_IN_DIRECT nebo METHOD_OUT_DIRECT
Určuje přímou vstupně-výstupní metodu, která se obvykle používá ke čtení nebo zápisu velkých objemů dat pomocí DMA nebo PIO, která se musí rychle přenést.

Zadejte METHOD_IN_DIRECT, pokud volající DeviceIoControl nebo IoBuildDeviceIoControlRequest budou předávat data ovladači.

Zadejte METHOD_OUT_DIRECT, pokud volající deviceIoControl nebo IoBuildDeviceIoControlRequest obdrží data z ovladače.

Informace o tom, jak systém určuje vyrovnávací paměti dat pro METHOD_IN_DIRECT a METHOD_OUT_DIRECT V/V řídicí kódy, naleznete v tématu Popisy vyrovnávací paměti pro vstupně-výstupní řídicí kódy.

Další informace o přímých vstupně-výstupních operacích naleznete v tématu Použití přímých vstupně-výstupních operací.

METHOD_NEITHER
Určuje , že nejsou v vyrovnávací paměti ani přímé vstupně-výstupní operace. Správce vstupně-výstupních operací neposkytuje žádné systémové vyrovnávací paměti ani MDLs. IRP poskytuje virtuální adresy uživatelského režimu vstupních a výstupních vyrovnávacích pamětí zadaných pro DeviceIoControl nebo IoBuildDeviceIoControlRequest bez ověření nebo mapování.

Informace o tom, jak systém určuje vyrovnávací paměti dat pro METHOD_NEITHER vstupně-výstupní řídicí kódy, naleznete v tématu Popisy vyrovnávací paměti pro vstupně-výstupní řídicí kódy.

Tuto metodu lze použít pouze v případě, že je možné zaručit, že ovladač běží v kontextu vlákna, které pochází z žádosti o řízení vstupně-výstupních operací. Je zaručeno, že tuto podmínku splní pouze ovladač režimu jádra nejvyšší úrovně, takže METHOD_NEITHER se zřídka používá pro kódy řízení vstupně-výstupních operací, které se předávají ovladačům zařízení nízké úrovně.

U této metody musí ovladač nejvyšší úrovně určit, zda má být nastavena vyrovnávací paměť nebo přímý přístup k uživatelským datům při přijetí požadavku, případně musí uzamknout vyrovnávací paměť uživatele a musí zabalit svůj přístup k vyrovnávací paměti uživatele ve strukturované obslužné rutině výjimky (viz zpracování výjimek). V opačném případě může volající v uživatelském režimu změnit data uložená ve vyrovnávací paměti dříve, než je ovladač může použít, nebo může být volající vykázán z paměti právě ve chvíli, kdy ovladač přistupuje k uživatelské vyrovnávací paměti.

Další informace naleznete v tématu Použití žádné vyrovnávací paměti ani přímé vstupně-výstupní operace.

RequiredAccess
Určuje typ přístupu, který volající musí požadovat při otevření objektu souboru, který představuje zařízení (viz IRP_MJ_CREATE). Správce vstupně-výstupních operací vytvoří IRP a zavolá ovladač s konkrétním kódem IO řízení pouze v případě, že volající požádal o specifikovaná přístupová práva. RequiredAccess je určen pomocí následujících systémově definovaných konstant:

FILE_JAKÝKOLI_PŘÍSTUP
Správce vstupně-výstupních operací odešle IRP pro všechny volající, kteří mají popisovač objektu souboru, který představuje objekt cílového zařízení.

FILE_READ_DATA
Správce vstupně-výstupních operací odešle protokol IRP jenom pro volajícího s přístupovými právy ke čtení a umožní ovladači základního zařízení přenášet data ze zařízení do systémové paměti.

FILE_WRITE_DATA
Správce vstupně-výstupních operací odešle protokol IRP jenom pro volajícího s přístupovými právy k zápisu a umožní ovladači základního zařízení přenášet data ze systémové paměti do jeho zařízení.

FILE_READ_DATA a FILE_WRITE_DATA mohou být zkombinovány pomocí operace OR dohromady, pokud volající musí mít přístupová práva ke čtení i zápisu.

Některé kódy řízení vstupně-výstupních operací definované systémem mají hodnotu RequiredAccess FILE_ANY_ACCESS, která volajícímu umožňuje odeslat konkrétní hodnotu IOCTL bez ohledu na přístup udělený zařízení. Mezi příklady patří řídicí kódy vstupně-výstupních operací, které se odesílají ovladačům exkluzivních zařízení.

Jiné kódy řízení vstupně-výstupních operací definovaných systémem vyžadují, aby volající měl přístupová práva ke čtení, přístupová práva k zápisu nebo obojí. Například následující definice kódu pro řízení veřejných vstupně-výstupních operací IOCTL_DISK_SET_PARTITION_INFO ukazuje, že tento vstupně-výstupní požadavek lze odeslat ovladači pouze v případě, že volající má přístupová práva ke čtení i zápisu:

#define IOCTL_DISK_SET_PARTITION_INFO\
        CTL_CODE(IOCTL_DISK_BASE, 0x008, METHOD_BUFFERED,\
        FILE_READ_DATA | FILE_WRITE_DATA)

Poznámka:

Než zadáte FILE_ANY_ACCESS pro nový kód IOCTL, musíte mít naprosto jistotu, že povolení neomezeného přístupu k vašemu zařízení nevytváří možnou cestu pro uživatele se zlými úmysly k ohrožení systému.

Ovladače mohou použít IoValidateDeviceIoControlAccess k provádění přísnější kontroly přístupu, než která poskytuje bity RequiredAccess IOCTL.

Další užitečná makra

Následující makra jsou užitečná pro extrahování 16bitového pole DeviceType a 2bitového typu TransferType z kódu IOCTL:

#define DEVICE_TYPE_FROM_CTL_CODE(ctrlCode)   (((ULONG)(ctrlCode & 0xffff0000)) >> 16)
#define METHOD_FROM_CTL_CODE(ctrlCode)        ((ULONG)(ctrlCode & 3))

Tato makra jsou definována v wdm.h a Ntddk.h.