Dela via


Definiera I/O-kontrollkoder

Den här artikeln beskriver hur du skapar en unik I/O-kontrollkod (IOCTL). IOCTL:er kan vara:

  • Offentliga IOCTL:er, som vanligtvis är systemdefinierade och dokumenterade av Microsoft.
  • Privata IOCTL:er, som vanligtvis är avsedda att användas uteslutande av en leverantörs programvarukomponenter för att kommunicera med varandra. De definieras vanligtvis i en leverantörs huvudfil och dokumenteras inte av Microsoft.

IOCTL-layout

En IOCTL är ett 32-bitars värde som består av flera fält. Följande bild illustrerar den bitvisa layouten för en IOCTL:

Diagram som illustrerar den bitvisa layouten för en 32-bitars i/o-kontrollkod.

Varje fält i IOCTL har ett specifikt syfte, enligt beskrivningen i följande tabell:

Fält Bitar i IOCTL Beskrivning
Gemensam 31 Leverantörer måste ange den här biten när de använder ett leverantörstilldelat värde för DeviceType.
DeviceType 16-30 Identifierar typen av enhet. Det här värdet måste matcha värdet som anges i DeviceType-medlemmen i drivrutinens DEVICE_OBJECT struktur. Leverantörer bör använda ett värde från 32768 till 65535 (0x8000 via 0xffff) och ange Common-biten . Värden 0 till och med 32767 (0x0000 via 0x7fff) är reserverade för Microsoft. Mer information finns i Ange enhetstyper.
Tillträde 14-15 Anger vilken typ av åtkomst som en anropare måste begära när du öppnar filobjektet som representerar enheten (se IRP_MJ_CREATE). I/O-hanteraren skapar IRP:er och anropar drivrutinen med ett specifikt IOCTL endast om anroparen har begärt de angivna åtkomsträttigheterna. Det här fältet anges med hjälp av följande systemdefinierade konstanter: FILE_ANY_ACCESS, FILE_READ_DATA och FILE_WRITE_DATA.
Skräddarsydd tretton När värdet anges anger det att IOCTL är en leverantörsdefinierad IOCTL.
Funktion 2-12 Unik kod för den drivrutin som identifierar den funktion som den ska utföra. För en leverantörsskapad IOCTL använder du värdet 2048 till 4095 (0x800 via 0xfff) och anger anpassad bit. Värden som är mindre än 2048 (0x000 via 0x7ff) är reserverade för Microsoft.
Metod 0-1 Anger hur systemet ska skicka data mellan anroparen för DeviceIoControl (eller IoBuildDeviceIoControlRequest) och drivrutinen som hanterar IRP. Mer information finns i Vägledning för att ange metodbitar.

Makro för att definiera I/O-kontrollkoder

Använd det systemspecifika CTL_CODE makrot för att definiera nya I/O-kontrollkoder. Det här makrot definieras i devioctl.h enligt följande:

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

I föregående avsnitt finns en beskrivning av DeviceType, Funktion, Metod och Åtkomst.

Tänk på följande regler när du definierar nya I/O-kontrollkoder:

Definitionen av en ny IOCTL-kod, oavsett om den är avsedd för användning med IRP_MJ_DEVICE_CONTROL eller IRP_MJ_INTERNAL_DEVICE_CONTROL begäranden, använder följande format:

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

Välj ett beskrivande konstantnamn för IOCTL för formuläret IOCTL_Device_Function, där Enheten anger typen av enhet och Funktion anger åtgärden. Till exempel använder den systembaserade IOCTL_VIDEO_ENABLE_CURSOR konstanten "VIDEO" för Enhet och "ENABLE_CURSOR" för Funktion.

Vägledning för att ange åtkomstbitar

När du definierar en ny IOCTL måste du välja ett värde för fältet Åtkomstbit som anger vilken typ av åtkomst som en anropare måste begära när du öppnar filobjektet som representerar enheten. I/O-hanteraren skapar IRP:er och anropar drivrutinen med en särskild IOCTL endast om anroparen begärde de angivna åtkomsträttigheterna.

Åtkomst anges med hjälp av följande systemdefinierade konstanter:

  • FILE_ANY_ACCESS

    I/O-hanteraren skickar IRP till alla anropare som har en referens till filobjektet som representerar målenhetsobjektet. Innan du anger FILE_ANY_ACCESS för en ny IOCTL-kod måste du vara helt säker på att om du tillåter obegränsad åtkomst till enheten inte skapar en möjlig sökväg för skadliga användare att kompromettera systemet.

  • LÄSA_FILDATA

    I/O-chefen skickar endast IRP för en anropare med läsbehörighet, vilket gör att den underliggande enhetsdrivrutinen kan överföra data från enheten till systemminnet.

  • FILE_SKRIV_DATA

    I/O-chefen skickar endast IRP för en anropare med skrivbehörighet, vilket gör att den underliggande enhetsdrivrutinen kan överföra data från systemminnet till enheten.

FILE_READ_DATA och FILE_WRITE_DATA kan kopplas samman om anroparen måste ha både läs- och skrivbehörighet.

Vissa systemdefinierade I/O-kontrollkoder har ett åtkomstvärde på FILE_ANY_ACCESS, vilket gör att anroparen kan skicka det specifika IOCTL-värdet oavsett vilken åtkomst som beviljas till enheten. Exempel är I/O-kontrollkoder som skickas till drivrutiner för exklusiva enheter.

Andra systemdefinierade I/O-kontrollkoder kräver att anroparen har läsbehörighet, skrivbehörighet eller båda. Följande definition av den offentliga IOCTL_DISK_SET_PARTITION_INFO IOCTL visar till exempel att denna I/O-begäran endast kan skickas till en drivrutin om anroparen har både läs- och skrivbehörighet:

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

Drivrutiner kan använda IoValidateDeviceIoControlAccess för att utföra striktare åtkomstkontroll än den som tillhandahålls av åtkomstbitarna i IOCTL.

Vägledning för att ange metodbitar

När du definierar en ny IOCTL måste du välja ett värde för fältet Metodbit som anger hur systemet ska skicka data mellan anroparen för DeviceIoControl (eller IoBuildDeviceIoControlRequest) och drivrutinen som hanterar IRP.

Använd någon av följande systemdefinierade konstanter för att ange fältet Metod .

  • METOD_BUFFRAD

    Anger den buffrade I/O--metoden, som vanligtvis används för överföring av små mängder data per begäran. De flesta I/O-kontrollkoder för enheter och mellanliggande drivrutiner använder det här värdet.

    Information om hur systemet anger databuffertar för METHOD_BUFFERED I/O-kontrollkoder finns i Buffertbeskrivningar för I/O-kontrollkoder.

    Mer information om buffrad I/O finns i Använda buffrad I/O-.

  • METHOD_IN_DIRECT eller METHOD_OUT_DIRECT

    Anger den direkta I/O-metoden , som vanligtvis används för att läsa eller skriva stora mängder data med hjälp av DMA eller PIO som måste överföras snabbt.

    • Ange METHOD_IN_DIRECT om anroparen för DeviceIoControl eller IoBuildDeviceIoControlRequest skickar data till drivrutinen.

    • Ange METHOD_OUT_DIRECT om anroparen för DeviceIoControl eller IoBuildDeviceIoControlRequest ska ta emot data från drivrutinen.

    Information om hur systemet anger databuffertar för METHOD_IN_DIRECT och METHOD_OUT_DIRECT I/O-kontrollkoder finns i Buffer Descriptions for I/O Control Codes.

    Mer information om direkt I/O finns i Using Direct I/O.

  • METHOD_NEITHER

    Anger att I/O-metoden inte är buffrad eller direkt. I/O-chefen tillhandahåller inga systembuffertar eller MDL:er. IRP tillhandahåller de virtuella adresserna i användarläge för in- och utdatabuffertar som har angetts för DeviceIoControl- eller IoBuildDeviceIoControlRequest, utan att verifiera eller mappa dem.

    Information om hur systemet anger databuffertar för METHOD_NEITHER I/O-kontrollkoder finns i Buffertbeskrivningar för I/O-kontrollkoder.

    Den här metoden kan endast användas om drivrutinen garanterat körs i kontexten för den tråd som initierade I/O-kontrollbegäran. Endast en drivrutin i kernelläge på högsta nivå är garanterad att uppfylla det här villkoret, så METHOD_NEITHER används sällan för IOCTL:er som skickas till drivrutiner på låg nivå.

    Med den här metoden är drivrutinen på högsta nivå:

    • Måste avgöra om du vill konfigurera buffrad eller direkt åtkomst till användardata när begäran tas emot.
    • Eventuellt måste du låsa användarbufferten.
    • Måste omsluta sin åtkomst till användarbufferten i en strukturerad undantagshanterare (se Hantera undantag).

    Annars kan anroparen i användarläge ändra buffrade data innan drivrutinen kan använda dem, eller så kan anroparen växlas ut precis när drivrutinen har åtkomst till användarbufferten.

    För mer information, se Varken buffrad eller direkt I/O används.

Andra användbara makron

Följande makron är användbara för att extrahera fälten 16-bitars DeviceType och 2-bitarsmetoden från en IOCTL.

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

Dessa makron definieras i Wdm.h och Ntddk.h.