Sdílet prostřednictvím


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

Tento článek popisuje, jak vytvořit jedinečný kód IOCTL. IOCTLs mohou být:

  • Veřejné IOCTLs, které jsou obvykle systémově definované a zdokumentované společností Microsoft.
  • Privátní IOCTLs, které jsou obvykle určeny výhradně pro vzájemnou komunikaci softwarových komponent dodavatele. Obvykle jsou definovány v souboru hlaviček dodavatele a nejsou zdokumentované Společností Microsoft.

Rozložení IOCTL

Hodnota IOCTL je 32bitová hodnota, která se skládá z několika polí. Následující obrázek znázorňuje bitové uspořádání IOCTL.

Diagram znázorňující bitové rozložení 32bitového i/o řídicího kódu

Každé pole v IOCTL má specifický účel, jak je popsáno v následující tabulce:

Obor Bity v IOCTL Popis
Společné 31 Dodavatelé musí tento bit nastavit, pokud pro DeviceType používají hodnotu přiřazenou dodavatelem.
TypZařízení 16-30 Určuje typ zařízení. Tato hodnota se musí shodovat s hodnotou nastavenou v členu DeviceType struktury DEVICE_OBJECT ovladače. Dodavatelé by měli použít hodnotu od 32768 do 65535 (0x8000 až 0xffff) a měli by nastavit běžný bit. Hodnoty 0 až 32767 (0x0000 až 0x7fff) jsou vyhrazené pro Microsoft. Další informace naleznete v tématu Určení typů zařízení.
Přístup 14-15 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í hodnotou IOCTL pouze v případě, že volající požadoval zadaná přístupová práva. Toto pole je určeno pomocí následujících systémově definovaných konstant: FILE_ANY_ACCESS, FILE_READ_DATA a FILE_WRITE_DATA.
na míru 13 Při nastavení to označuje, že IOCTL je definováno dodavatelem.
Funkce 2-12 Jedinečný kód pro ovladač, který identifikuje funkci, kterou má provést. Pro hodnotu IOCTL vytvořenou dodavatelem použijte hodnotu v rozsahu od 2048 do 4095 (0x800 až 0xfff) a nastavte bit Vlastní. Hodnoty menší než 2048 (0x000 až 0x7ff) jsou vyhrazené pro Microsoft.
Metoda 0-1 Určuje, jak má systém předávat data mezi volajícím DeviceIoControl (nebo IoBuildDeviceIoControlRequest) a ovladačem, který zpracovává IRP. Další informace naleznete v části Pokyny k nastavení bitů metody.

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

Pomocí systémového CTL_CODE makra definujte nové kódy ovládacích prvků vstupně-výstupních operací. Toto makro je definováno v souboru devioctl.h následujícím způsobem:

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

Popis deviceType, Function, Method a Access najdete v předchozí části.

Při definování nových kódů ovládacích prvků vstupně-výstupních operací mějte na paměti následující pravidla:

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 indikuje operaci. Například systém dodávaná IOCTL_VIDEO_ENABLE_CURSOR konstanta používá "VIDEO" pro zařízení a "ENABLE_CURSOR" pro funkci.

Pokyny k nastavení bitů Accessu

Při definování nové hodnoty IOCTL musíte zvolit hodnotu pro bitové pole Accessu , která označuje typ přístupu, který volající musí požádat při otevření objektu souboru, který představuje zařízení. Správce vstupně-výstupních operací vytvoří IRP a zavolá ovladač s konkrétním IOCTL pouze v případě, že volající požaduje specifická přístupová práva.

Access je určen pomocí následujících systémově definovaných konstant:

  • FILE_ANY_ACCESS

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

  • ČTENÍ_DAT_Z_SOUBORU

    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 (zápis dat do souboru)

    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 Access 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 veřejné IOCTL_DISK_SET_PARTITION_INFO IOCTL 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)

Ovladače mohou použít IoValidateDeviceIoControlAccess k provádění přísnější kontroly přístupu, než jakou nabízejí přístupové bity IOCTL.

Pokyny k nastavení bitů metody

Při definování nové hodnoty IOCTL musíte zvolit hodnotu pro pole Bit Method , která označuje, jak má systém předávat data mezi volajícím DeviceIoControl (nebo IoBuildDeviceIoControlRequest) a ovladačem, který zpracovává IRP.

K nastavení pole Metoda použijte jednu z následujících systémově definovaných konstant.

  • METHOD_UKLÁDANÝ

    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 tuto hodnotu používá.

    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 předá 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í.

  • METODA_ANI_JEDNA

    Určuje , že vstupně-výstupní metoda není ukládána do vyrovnávací paměti ani není přímá. Správce vstupně-výstupních operací neposkytuje žádné systémové vyrovnávací paměti ani knihovny 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 zaručeno, že ovladač běží v kontextu vlákna, které pochází z žádosti o řízení vstupně-výstupních operací. Tento stav zaručuje pouze ovladač režimu jádra nejvyšší úrovně, takže metoda METHOD_NEITHER se zřídka používá pro IOCTLs, které se předávají ovladačům zařízení nízké úrovně.

    Tímto způsobem ovladač nejvyšší úrovně:

    • Musí určit, jestli se má nastavit vyrovnávací paměť nebo přímý přístup k uživatelským datům při přijetí žádosti.
    • Možná musí uzamknout uživatelský pufr.
    • Musí zabalit přístup k vyrovnávací paměti uživatele do strukturované obslužné rutiny výjimek (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.

Další užitečná makra

Následující makra jsou užitečná pro extrahování 16bitového pole DeviceType a 2bitového pole Metoda z hodnoty 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.