WdfDeviceInitAssignWdmIrpPreprocessCallback, fonction (wdfdevice.h)
[S’applique uniquement à KMDF]
La méthode WdfDeviceInitAssignWdmIrpPreprocessCallback inscrit une fonction de rappel pour gérer un code de fonction principale IRP et, éventuellement, un ou plusieurs codes de fonction mineurs associés au code de fonction principale.
Syntaxe
NTSTATUS WdfDeviceInitAssignWdmIrpPreprocessCallback(
[in] PWDFDEVICE_INIT DeviceInit,
[in] PFN_WDFDEVICE_WDM_IRP_PREPROCESS EvtDeviceWdmIrpPreprocess,
[in] UCHAR MajorFunction,
[in, optional] PUCHAR MinorFunctions,
[in] ULONG NumMinorFunctions
);
Paramètres
[in] DeviceInit
Pointeur vers une structure WDFDEVICE_INIT .
[in] EvtDeviceWdmIrpPreprocess
Pointeur vers la fonction de rappel EvtDeviceWdmIrpPreprocess du pilote.
[in] MajorFunction
Un des codes de fonction principale IRP définis dans wdm.h.
[in, optional] MinorFunctions
Pointeur vers un tableau d’un ou plusieurs codes de fonction mineure IRP associés au code de fonction principale spécifié. Ce paramètre est facultatif et peut être NULL. Pour plus d'informations, consultez la section Notes qui suit.
[in] NumMinorFunctions
Nombre de codes de fonction mineurs contenus dans le tableau MinorFunctions .
Valeur retournée
Si l’opération réussit, la méthode retourne STATUS_SUCCESS. Les valeurs de retour supplémentaires sont les suivantes :
Code de retour | Description |
---|---|
|
La valeur MajorFunction n’est pas valide. |
|
La mémoire est insuffisante. |
|
Le pilote a précédemment inscrit un tableau MinorFunctions pour cette fonction majeure et tente de spécifier à nouveau des fonctions mineures pour le code MajorFunction spécifié. |
La méthode peut retourner d’autres valeurs NTSTATUS.
Remarques
Les pilotes peuvent appeler la méthode WdfDeviceInitAssignWdmIrpPreprocessCallback pour deux raisons :
-
Pour gérer un code de fonction IRP majeur ou mineur que l’infrastructure ne prend pas en charge.
Par exemple, l’infrastructure ne prend pas en charge IRP_MJ_FLUSH_BUFFERS. Si votre pilote doit prendre en charge cette IRP, il doit inscrire une fonction de rappel EvtDeviceWdmIrpPreprocess qui gère l’IRP. Le pilote doit suivre les règles WDM pour le traitement des IRPs.
-
Pour prétraiter un IRP avant que l’infrastructure ne le gère.
Dans de rares cas, il peut être nécessaire qu’un pilote traite un IRP avant que l’infrastructure ne le traite. Dans ce cas, la fonction de rappel EvtDeviceWdmIrpPreprocess du pilote peut traiter l’IRP, puis appeler WdfDeviceWdmDispatchPreprocessedIrp pour renvoyer l’IRP au framework. Selon le code de fonction de l’IRP, l’infrastructure peut traiter l’IRP lui-même ou remettre à nouveau l’IRP au pilote dans un objet de requête d’infrastructure.
Si le pointeur du tableau MinorFunctions a la valeur NULL, l’infrastructure appelle la fonction de rappel pour tous les codes de fonction mineurs associés au code de fonction principale spécifié. Si le pointeur du tableau MinorFunctions n’est pas NULL, l’infrastructure effectue une copie du tableau afin que le pilote n’ait pas à conserver définitivement son tableau.
Si le pilote a reçu un pointeur DeviceInit de WdfPdoInitAllocate ou une fonction de rappel d’événement EvtChildListCreateDevice , la fonction de rappel EvtDeviceWdmIrpPreprocess du pilote ne peut pas définir une routine d’achèvement pour les irPs qui contiennent un code de fonction principal de IRP_MJ_PNP. Sinon, Driver Verifier signale une erreur.
Si votre pilote appelle WdfDeviceInitAssignWdmIrpPreprocessCallback une ou plusieurs fois, l’infrastructure incrémente le membre StackSize de la structure wdM DEVICE_OBJECT du pilote une fois. Par conséquent, le gestionnaire d’E/S ajoute un emplacement de pile d’E/S supplémentaire à tous les IRP afin que la fonction de rappel EvtDeviceWdmIrpPreprocess puisse définir une routine IoCompletion . Notez que cet emplacement de pile d’E/S supplémentaire est ajouté à tous les IRPs, et pas seulement à ceux qui contiennent un code de fonction principale IRP que vous spécifiez dans un appel à WdfDeviceInitAssignWdmIrpPreprocessCallback. Par conséquent, pour éviter d’augmenter inutilement l’utilisation par votre pilote du pool de mémoire non paginée, vous devez éviter d’utiliser WdfDeviceInitAssignWdmIrpPreprocessCallback , sauf s’il n’existe aucune alternative.
Si votre pilote appelle WdfDeviceInitAssignWdmIrpPreprocessCallback plusieurs fois pour le même code majeur, l’infrastructure conserve uniquement la fonction de rappel EvtDeviceWdmIrpPreprocess la plus récente pour ce code majeur. (Votre pilote ne peut pas inscrire plusieurs rappels de prétraitement pour un seul code majeur.)
Pour plus d’informations sur la méthode WdfDeviceInitAssignWdmIrpPreprocessCallback , consultez Gestion des IRPs WDM en dehors de l’infrastructure.
Exemples
L’exemple de code suivant définit une fonction de rappel d’événement EvtDeviceWdmIrpPreprocess , puis inscrit la fonction de rappel pour gérer IRP_MJ_QUERY_INFORMATION IRPs.
NTSTATUS
SerialQueryInformationFile(
IN WDFDEVICE Device,
IN PIRP Irp
)
/*++
Routine Description:
This routine is used to query the end of file information on
the opened serial port. Any other file information request
is returned with an invalid parameter.
This routine always returns an end of file of 0.
Arguments:
DeviceObject - Pointer to the device object for this device
Irp - Pointer to the IRP for the current request
Return Value:
The function value is the final status of the call
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, ">SerialQueryInformationFile(%p, %p)\n", Device, Irp);
PAGED_CODE();
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Irp->IoStatus.Information = 0L;
Status = STATUS_SUCCESS;
if (IrpSp->Parameters.QueryFile.FileInformationClass ==
FileStandardInformation) {
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(FILE_STANDARD_INFORMATION))
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
PFILE_STANDARD_INFORMATION Buf = Irp->AssociatedIrp.SystemBuffer;
Buf->AllocationSize.QuadPart = 0;
Buf->EndOfFile = Buf->AllocationSize;
Buf->NumberOfLinks = 0;
Buf->DeletePending = FALSE;
Buf->Directory = FALSE;
Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
}
} else if (IrpSp->Parameters.QueryFile.FileInformationClass ==
FilePositionInformation) {
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(FILE_POSITION_INFORMATION))
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
((PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->
CurrentByteOffset.QuadPart = 0;
Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
}
} else {
Status = STATUS_INVALID_PARAMETER;
}
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
SerialEvtDeviceAdd(
IN WDFDRIVER Driver,
IN PWDFDEVICE_INIT DeviceInit
)
{
...
status = WdfDeviceInitAssignWdmIrpPreprocessCallback(
DeviceInit,
SerialQueryInformationFile,
IRP_MJ_QUERY_INFORMATION,
NULL, // Pointer to the minor function table
0 // Number of entries in the table
);
if (!NT_SUCCESS(status)) {
return status;
}
...
}
Configuration requise
Condition requise | Valeur |
---|---|
Plateforme cible | Universal |
Version KMDF minimale | 1.0 |
En-tête | wdfdevice.h (include Wdf.h) |
Bibliothèque | Wdf01000.sys (consultez Gestion de version de la bibliothèque d’infrastructure.) |
IRQL | <= DISPATCH_LEVEL |
Règles de conformité DDI | ChildDeviceInitAPI(kmdf),ControlDeviceInitAPI(kmdf),DeviceInitAPI(kmdf), DriverCreate(kmdf), InitFreeDeviceCallback(kmdf), InitFreeDeviceCreate(kmdf), InitFreeNull(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), PdoDeviceInitAPI(kmdf), PdoInitFreeDeviceCallback(kmdf), PdoInitFreeDeviceCreate(kmdf) |