La fonction dispatch, c'est l'aiguillage du driver. Elle a été connectée
au démarrage du driver
On récupère le contexte du driver (extension), la requête de l'appelant (irp)
la copie du tampon de l'appelant (iobuffer)
Notez que si le programme appelant transmet deux
tampons séparés, le driver n'en utilise qu'un. Le tampon d'entrée est copié
par le système dans le tampon du driver. à la fin du traitement, le tampon du
driver est copié dans le tampon de sortie du programme appelant.
Suivant l'ioctl appelant, on peut faire le travail tout de suite et rendre un
status STATUS_SUCCESS. Si d'autre traitements sont nécessaire (ex réceptions
sous it) il faut rendre un ntStatus = STATUS_PENDING;Le programme
appelant reste suspendu jusqu'à ce que d'autres traitements renvoient
STATUS_SUCCESS sur cette irp.
En attendant, le driver continuera à traiter d'autres irps.
// simpldrvit.c driver it en mode kernel
extern "C"
{
#include "ntddk.h"
#include "stdarg.h"
#include "stdio.h"
}
extern "C"
{
// interfaces externes/interne
#include "driver.h"
}
//********************************************************************************************
// fonction de dispatching du driver pour recupérer l'IRP
NTSTATUS MonDriverDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
ULONG ioControlCode;
NTSTATUS ntStatus;
ULONG inputBufferLength;
ULONG outputBufferLength;
PVOID ioBuffer;
KIRQL savIrq;
long wait; // pour traitement time out
// char *message;
Irp->IoStatus.Status = STATUS_SUCCESS; // retour de l'IRP
Irp->IoStatus.Information = 0;
// recupère le point d'entrée pour le code fonction et les paramêtres dans l'IRP
irpStack = IoGetCurrentIrpStackLocation (Irp);
// récupère l'extension du device Object
deviceExtension = (class deviceExtension *)DeviceObject->DeviceExtension;
// récupère les infos sur les buffers
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
wait = 0; // à priori pas de mise en attente de l'irp
// récupère le code fonction et appelle la bonne fonction en conséquence
switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE: // lors de la fonction Create file
break;
case IRP_MJ_CLOSE: // lors de la fermeture du fichier
CloseHandle
break;
case IRP_MJ_DEVICE_CONTROL: // lors d'un appel par DEVICEIO
// récupération du code de controle passé au driver par DEVICEIO
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode)
{
//
// Pour chaque code ioctl défini
dans l'interface
case IOCTL_IOCTL_RE_INITIALIZE :
if((inputBufferLength != sizeof(TMonDriverMsgInRE_INITIALIZE))
|| (outputBufferLength < sizeof(MonDriverMsgOutRE_INITIALIZE)) )
Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
else
{
TMonDriverMsgInRE_INITIALIZE *msgIn = (TMonDriverMsgInRE_INITIALIZE *) ioBuffer;
TMonDriverRE_INITIALIZE *msgOut = (TMonDriverMsgOutRE_INITIALIZE *) ioBuffer;
//
// code de traitement de la demande
Irp->IoStatus.Information = sizeof(TMonDriverNtMsgOutRE_INITIALIZE);
Irp->IoStatus.Status = STATUS_SUCCESS;
};
case autre ioctl....
}
return ntStatus; // succes ou erreur
}