Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In dit artikel wordt beschreven hoe u een unieke I/O-besturingscode (IOCTL) maakt. IOCTL's kunnen het volgende zijn:
- Openbare IOCTL's, die doorgaans door het systeem zijn gedefinieerd en gedocumenteerd door Microsoft.
- Privé-IOCTL's, die doorgaans uitsluitend door de softwareonderdelen van een leverancier moeten worden gebruikt om met elkaar te communiceren. Ze worden meestal gedefinieerd in het headerbestand van een leverancier en worden niet gedocumenteerd door Microsoft.
IOCTL-indeling
Een IOCTL is een 32-bits waarde die uit verschillende velden bestaat. In de volgende afbeelding ziet u de bitgewijze indeling van een IOCTL:
Elk veld in de IOCTL heeft een specifiek doel, zoals beschreven in de volgende tabel:
| Veld | Bits in IOCTL | Beschrijving |
|---|---|---|
| Gemeenschappelijk | 31 | Leveranciers moeten deze bit instellen wanneer ze een door de leverancier toegewezen waarde voor DeviceType gebruiken. |
| DeviceType | 16-30 | Hiermee wordt het type apparaat geïdentificeerd. Deze waarde moet overeenkomen met de waarde die is ingesteld in het DeviceType-lid van de DEVICE_OBJECT structuur van het stuurprogramma. Leveranciers moeten een waarde van 32768 tot en met 65535 (0x8000 tot 0xffff) gebruiken en de algemene bit instellen. Waarden 0 tot en met 32767 (0x0000 tot en met 0x7fff) zijn gereserveerd voor Microsoft. Zie Apparaattypen opgeven voor meer informatie. |
| Toegang | 14-15 | Geeft het type toegang aan dat een beller moet aanvragen bij het openen van het bestandsobject dat het apparaat vertegenwoordigt (zie IRP_MJ_CREATE). De I/O-manager zal IRP's maken en de driver alleen met een bepaalde IOCTL aanroepen als de beller de opgegeven toegangsrechten heeft aangevraagd. Dit veld wordt opgegeven met behulp van de volgende door het systeem gedefinieerde constanten: FILE_ANY_ACCESS, FILE_READ_DATA en FILE_WRITE_DATA. |
| Aangepast | 13 | Wanneer deze optie is ingesteld, geeft u aan dat de IOCTL een door de leverancier gedefinieerde IOCTL is. |
| Functie | 2-12 | Unieke code voor het stuurprogramma waarmee de functie wordt geïdentificeerd die moet worden uitgevoerd. Gebruik voor een door de leverancier gemaakte IOCTL een waarde 2048 tot en met 4095 (0x800 tot 0xfff) en stel de aangepaste bit in. Waarden kleiner dan 2048 (0x000 tot en met 0x7ff) zijn gereserveerd voor Microsoft. |
| Methode | 0-1 | Geeft aan hoe het systeem gegevens doorgeeft tussen de aanroeper van DeviceIoControl (of IoBuildDeviceIoControlRequest) en het stuurprogramma dat de IRP verwerkt. Zie Richtlijnen voor het instellen van de methode-bits voor meer informatie. |
Macro voor het definiëren van I/O-besturingscodes
Gebruik de door het systeem geleverde CTL_CODE macro om nieuwe I/O-besturingscodes te definiëren. Deze macro wordt als volgt gedefinieerd in devioctl.h :
#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
Zie de voorgaande sectie voor een beschrijving van DeviceType, Function, Method en Access.
Houd rekening met de volgende regels bij het definiëren van nieuwe I/O-besturingscodes:
Als er een nieuwe IOCTL beschikbaar is voor softwareonderdelen in de gebruikersmodus, moet deze worden gebruikt met IRP_MJ_DEVICE_CONTROL aanvragen. Onderdelen in de gebruikersmodus roepen DeviceIoControl aan om IRP_MJ_DEVICE_CONTROL aanvragen te verzenden.
Als een nieuwe IOCTL alleen beschikbaar is voor onderdelen van kernelmodusstuurprogramma's, moet deze worden gebruikt met IRP_MJ_INTERNAL_DEVICE_CONTROL aanvragen. Onderdelen in de kernelmodus kunnen IRP_MJ_INTERNAL_DEVICE_CONTROL aanvragen maken door IoBuildDeviceIoControlRequest aan te roepen. Zie IOCTL-aanvragen maken in stuurprogramma's voor meer informatie.
De definitie van een nieuwe IOCTL-code, ongeacht of deze is bedoeld voor gebruik met IRP_MJ_DEVICE_CONTROL of IRP_MJ_INTERNAL_DEVICE_CONTROL aanvragen, gebruikt de volgende indeling:
#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)
Kies een beschrijvende constante naam voor de IOCTL van de vorm IOCTL_Device_Function, waarbij Device het type apparaat aangeeft en Function de bewerking aangeeft. De door het systeem geleverde IOCTL_VIDEO_ENABLE_CURSOR constante gebruikt bijvoorbeeld 'VIDEO' voor apparaat en 'ENABLE_CURSOR' voor functie.
Richtlijnen voor het instellen van de Access-bits
Wanneer u een nieuwe IOCTL definieert, moet u een waarde kiezen voor het Access-bitveld dat aangeeft welk type toegang een beller moet aanvragen bij het openen van het bestandsobject dat het apparaat vertegenwoordigt. De I/O-manager maakt IRP's en roept het stuurprogramma alleen aan met een specifieke IOCTL als de beller de gespecificeerde toegangsrechten heeft aangevraagd.
Toegang wordt opgegeven met behulp van de volgende door het systeem gedefinieerde constanten:
FILE_ANY_ACCESS
De I/O-manager verzendt de IRP voor elke beller die een ingang heeft naar het bestandsobject dat het doelapparaatobject vertegenwoordigt. Voordat u FILE_ANY_ACCESS opgeeft voor een nieuwe IOCTL-code, moet u er absoluut zeker van zijn dat onbeperkte toegang tot uw apparaat geen mogelijk pad maakt voor kwaadwillende gebruikers om inbreuk te maken op het systeem.
GegevensLadenVanBestand
De I/O-manager verzendt de IRP alleen voor een beller met leestoegangsrechten, zodat het onderliggende apparaatstuurprogramma gegevens van het apparaat kan overdragen naar het systeemgeheugen.
GEGEVENS_SCHRIJVEN_BESTAND
De I/O-manager verzendt de IRP alleen voor een beller met schrijftoegangsrechten, zodat het onderliggende apparaatstuurprogramma gegevens van het systeemgeheugen naar het apparaat kan overdragen.
FILE_READ_DATA en FILE_WRITE_DATA kunnen samen ORed zijn als de beller zowel lees- als schrijftoegangsrechten moet hebben.
Sommige door het systeem gedefinieerde I/O-besturingscodes hebben een toegangswaarde van FILE_ANY_ACCESS, waardoor de beller de specifieke IOCTL kan verzenden, ongeacht de toegang die aan het apparaat is verleend. Voorbeelden hiervan zijn I/O-besturingscodes die worden verzonden naar stuurprogramma's van exclusieve apparaten.
Voor andere door het systeem gedefinieerde I/O-besturingscodes moet de beller leesrechten, schrijftoegangsrechten of beide hebben. De volgende definitie van de openbare IOCTL_DISK_SET_PARTITION_INFO IOCTL geeft bijvoorbeeld aan dat deze I/O-aanvraag alleen naar een stuurprogramma kan worden verzonden als de beller zowel lees- als schrijftoegangsrechten heeft:
#define IOCTL_DISK_SET_PARTITION_INFO\
CTL_CODE(IOCTL_DISK_BASE, 0x008, METHOD_BUFFERED,\
FILE_READ_DATA | FILE_WRITE_DATA)
Stuurprogramma's kunnen IoValidateDeviceIoControlAccess gebruiken om strengere toegangscontroles uit te voeren dan die van de Access-bits van een IOCTL.
Richtlijnen voor het instellen van de methode-bits
Wanneer u een nieuwe IOCTL definieert, moet u een waarde kiezen voor het veld Methode-bit dat aangeeft hoe het systeem gegevens doorgeeft tussen de aanroeper van DeviceIoControl (of IoBuildDeviceIoControlRequest) en het stuurprogramma dat de IRP verwerkt.
Gebruik een van de volgende door het systeem gedefinieerde constanten om het veld Methode in te stellen.
METHODE_GEBUFFERD
Hiermee geeft u de in buffer geplaatste I/O-methode op, die doorgaans wordt gebruikt voor het overdragen van kleine hoeveelheden gegevens per aanvraag. De meeste I/O-besturingscodes voor apparaat- en tussenliggende stuurprogramma's gebruiken deze waarde.
Zie Bufferbeschrijvingen voor I/O-besturingscodes voor METHOD_BUFFERED voor informatie over hoe het systeem gegevensbuffers opgeeft voor METHOD_BUFFERED I/O-besturingscodes.
Zie Buffered I/O gebruiken voor meer informatie over gebufferde I/O.
METHOD_IN_DIRECT of METHOD_OUT_DIRECT
Hiermee specificeert u de directe I/O-methode, die doorgaans wordt gebruikt voor het lezen of schrijven van grote hoeveelheden gegevens met behulp van DMA of PIO die snel moeten worden overgedragen.
Geef METHOD_IN_DIRECT op als de aanroeper van DeviceIoControl of IoBuildDeviceIoControlRequest gegevens doorgeeft aan het stuurprogramma.
Geef METHOD_OUT_DIRECT op als de aanroeper van DeviceIoControl of IoBuildDeviceIoControlRequest gegevens van de driver zal ontvangen.
Zie Bufferbeschrijvingen voor I/O-besturingscodes voor METHOD_IN_DIRECT en METHOD_OUT_DIRECT voor informatie over hoe het systeem gegevensbuffers opgeeft voor METHOD_IN_DIRECT en METHOD_OUT_DIRECT I/O-besturingscodes.
Zie Direct I/O gebruiken voor meer informatie over directe I/O.
METHOD_NEITHER
Hiermee specificeert u dat de I/O-methode niet wordt gebufferd of rechtstreeks is. De I/O-manager biedt geen systeembuffers of MDL's. De IRP levert de virtuele adressen in de gebruikersmodus van de invoer- en uitvoerbuffers die zijn opgegeven voor DeviceIoControl of IoBuildDeviceIoControlRequest, zonder deze te valideren of toe te wijzen.
Zie Bufferbeschrijvingen voor I/O-besturingscodes voor I/O-besturingscodes voor informatie over hoe het systeem gegevensbuffers opgeeft voor METHOD_NEITHER I/O-besturingscodes.
Deze methode kan alleen worden gebruikt als het stuurprogramma gegarandeerd wordt uitgevoerd in de context van de thread die afkomstig is van de I/O-besturingsaanvraag. Alleen een stuurprogramma op het hoogste niveau in de kernelmodus voldoet aan deze voorwaarde, dus METHOD_NEITHER zelden wordt gebruikt voor IOCTL's die worden doorgegeven aan apparaatstuurprogramma's op laag niveau.
Met deze methode wordt het stuurprogramma op het hoogste niveau aangestuurd.
- Moet bepalen of er een buffer of directe toegang tot gebruikersgegevens moet worden ingesteld na ontvangst van de aanvraag.
- Mogelijk moet de gebruikersbuffer worden vergrendeld.
- De toegang tot de gebruikersbuffer moet worden verpakt in een gestructureerde uitzonderingshandler (zie Uitzonderingen verwerken).
Anders kan de aanroeper van de oorspronkelijke gebruikersmodus de gebufferde gegevens wijzigen voordat het stuurprogramma deze kan gebruiken, of kan de beller worden verwisseld, net zoals het stuurprogramma toegang heeft tot de gebruikersbuffer.
Zie Het gebruik van noch gebufferde noch directe I/O voor meer informatie.
Andere nuttige macro's
De volgende macro's zijn handig voor het extraheren van de 16-bits DeviceType - en 2-bits methodevelden uit een IOCTL.
#define DEVICE_TYPE_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0xffff0000)) >> 16)
#define METHOD_FROM_CTL_CODE(ctrlCode) ((ULONG)(ctrlCode & 3))
Deze macro's worden gedefinieerd in Wdm.h en Ntddk.h.