Artikel-ID: 320275 - Geändert am: Dienstag, 19. Juli 2005 - Version: 5.0

Verschiedene Möglichkeiten zum Behandeln von IRPs - betrügen Blatt (Teil 1 von 2)

SystemtippDieser Artikel bezieht sich auf ein anderes Betriebssystem als das von Ihnen verwendete. Für Sie möglicherweise nicht relevante Artikelinhalte wurden deaktiviert.

Auf dieser Seite

Alles erweitern | Alles schließen

Zusammenfassung

Einführung

Eine der am häufigsten ausgeführten Aufgaben in Windows Driver Model (WDM) Treiber ist Input-Output-Anforderungspakete (IRPs) aus einen Treiber an einen anderen Treiber gesendet. Ein Treiber entweder erstellt seine eigene IRP und sendet Sie an eine niedrigere Treiber, oder der Treiber leitet die IRPs, die von einem anderen Treiber empfängt, die über verbunden ist.

Dieser Artikel beschreibt alle Möglichkeiten, die ein Treiber mit einem niedrigeren Treiber mit Anmerkungen Beispielcode IRPs senden können. Je nach müssen werden Treiber Schreiber können eine der Vorlagen in diesem Artikel angegebenen folgen und von alten IRP von Nachrichtenbehandlungsregeln nicht betroffen.

Teil 1 dieses Thema zeigt 5 Szenarios dazu, wie ein IRP an einen anderen Treiber aus einer Dispatch-Routine weiterleiten, und die verbleibenden 7 Szenarien (in Teil 2 dieses Themas aufgelistet) beschreiben verschiedene Möglichkeiten zum Erstellen eine IRP und an einen anderen Treiber sendet. Teil 2 dieses Thema ist in der folgenden Knowledge Base enthalten:
326315  (http://support.microsoft.com/kb/326315/ ) Verschiedene Möglichkeiten zum Behandeln von IRPs - betrügen Blatt (Teil 2 von 2)
Bevor Sie die verschiedenen Szenarien untersuchen, Beachten Sie Folgendes über den STATUS, der vom Abschluss Routinen zurückgegeben wird:
Eine Routine IRP Abschluss kann entweder STATUS_MORE_PROCESSING_REQUIRED oder STATUS_SUCCESS zurückgeben.
Der e/A-Manager verwendet die folgenden Regeln, wenn den Status untersucht:
  • Wenn der Status STATUS_MORE_PROCESSING_REQUIRED, das IRP abschließen beenden ist die Stapel Position unverändert lassen, und zurückzugeben.
  • Wenn der Status etwas anderes als STATUS_MORE_PROCESSING_REQUIRED ist, fahren Sie das IRP nach oben durchführen.
Da der e/A-Manager keinen wissen, welcher Wert nicht STATUS_MORE_PROCESSING_REQUIRED verwendet wird, verwenden Sie STATUS_SUCCESS (da der Wert 0 effizient geladen werden die meisten Prozessorarchitekturen ist).

Um die Lesbarkeit des Codes zu verbessern, Windows XP SP1 und Windows XP .NET Driver Development Kit Ntddk.h und wdm.h Headerdateien haben eine neue # define mit dem Namen STATUS_CONTINUE_COMPLETION, der Alias STATUS_SUCCESS wie im folgenden Code gezeigt:
// 
// This value should be returned from completion routines to continue
// completing the IRP upwards. Otherwise, STATUS_MORE_PROCESSING_REQUIRED
// should be returned.
// 
#define STATUS_CONTINUE_COMPLETION      STATUS_SUCCESS
// 
// Completion routines can also use this enumeration instead of status codes.
// 
typedef enum _IO_COMPLETION_ROUTINE_RESULT {
    
    ContinueCompletion = STATUS_CONTINUE_COMPLETION,
    StopCompletion = STATUS_MORE_PROCESSING_REQUIRED

} IO_COMPLETION_ROUTINE_RESULT, *PIO_COMPLETION_ROUTINE_RESULT;
				

Weitere Informationen

Szenario 1: Weiterleiten und vergessen

Verwenden Sie den folgenden Code, wenn ein Treiber nur möchte das IRP nach unten weiterleiten und keine weitere Aktion in Anspruch nehmen. Der Treiber hat keinen in diesem Fall eine Beendigung-Routine festgelegt. Wenn der Treiber einen Treiber auf oberster Ebene ist, kann das IRP synchron oder asynchron, je nach dem Status abgeschlossen werden, die von der unteren Treiber zurückgegeben wird.
NTSTATUS
DispatchRoutine_1(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    // 
    // You are not setting a completion routine, so just skip the stack
    // location because it provides better performance.
    // 
    IoSkipCurrentIrpStackLocation (Irp);
    return IoCallDriver(TopOfDeviceStack, Irp);
} 

Szenario 2: Weiterleiten, und warten

Verwenden Sie den folgenden Code, wenn ein Treiber möchte IRP einen niedrigeren Treiber weiterleiten und warten Sie, um zurückzukehren, damit er das IRP verarbeiten kann. Dies geschieht häufig bei der Behandlung Plug & Play-IRPs. Z. B. Wenn Sie eine IRP_MN_START_DEVICE IRP erhalten, müssen das IRP an den Bustreiber weitergeleitet und warten Sie abschließen, bevor Sie Ihr Gerät starten können. Das Windows-System hat eine neue Funktion mit dem Namen IoForwardIrpSynchronously , die Sie diesen Vorgang einfach dazu verwenden können.
NTSTATUS
DispatchRoutine_2(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    KEVENT   event;
    NTSTATUS status;

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    // 
    // You are setting completion routine, so you must copy
    // current stack location to the next. You cannot skip a location
    // here.
    // 
    IoCopyCurrentIrpStackLocationToNext(Irp);

    IoSetCompletionRoutine(Irp,
                           CompletionRoutine_2,
                           &event,
                           TRUE,
                           TRUE,
                           TRUE
                           );

    status = IoCallDriver(TopOfDeviceStack, Irp);

    if (status == STATUS_PENDING) {
        
       KeWaitForSingleObject(&event,
                             Executive, // WaitReason
                             KernelMode, // must be Kernelmode to prevent the stack getting paged out
                             FALSE,
                             NULL // indefinite wait
                             );
       status = Irp->IoStatus.Status;
    }
    
    // <---- Do your own work here.


    // 
    // Because you stopped the completion of the IRP in the CompletionRoutine
    // by returning STATUS_MORE_PROCESSING_REQUIRED, you must call
    // IoCompleteRequest here.
    // 
    IoCompleteRequest (Irp, IO_NO_INCREMENT);
    return status;

}
NTSTATUS
CompletionRoutine_2(
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )
{ 
  if (Irp->PendingReturned == TRUE) {
    // 
    // You will set the event only if the lower driver has returned
    // STATUS_PENDING earlier. This optimization removes the need to
    // call KeSetEvent unnecessarily and improves performance because the
    // system does not have to acquire an internal lock.  
    // 
    KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
  }
  // This is the only status you can return. 
  return STATUS_MORE_PROCESSING_REQUIRED;  
} 
				

Szenario 3: Weiter mit einer Routine Abschluss

In diesem Fall der Treiber legt eine Routine Abschluss, leitet das IRP nach unten und dann der Status der niedrigere Treiber unverändert zurückgegeben. Festlegen der Abschluss Routine dient so ändern Sie den Inhalt der IRP auf dem Weg zurück.
NTSTATUS
DispathRoutine_3(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    NTSTATUS status;

    // 
    // Because you are setting completion routine, you must copy the
    // current stack location to the next. You cannot skip a location
    // here.
    // 
    IoCopyCurrentIrpStackLocationToNext(Irp); 

    IoSetCompletionRoutine(Irp,
                           CompletionRoutine_31,// or CompletionRoutine_32
                           NULL,
                           TRUE,
                           TRUE,
                           TRUE
                           );
    
    return IoCallDriver(TopOfDeviceStack, Irp);

} 
Wenn Sie den Status der niedrigeren Treiber aus Ihre Dispatch-Routine zurückgeben:
  • Sie müssen den Status der IRPs in der Abschluss nicht ändern. Sicherstellen, dass der Status-Werte in der IRP-IoStatus festgelegt ist Block (-> IoStatus.Status Irp) sind identisch mit den Rückgabestatus des unteren Treiber.
  • Gemäß Irp-> PendingReturned, müssen Sie den ausstehenden Status das IRP weitergeben.
  • Sie müssen die Synchronicity der IRP nicht ändern.
As a result, there are only 2 valid versions of the completion routine in this scenario (31 and 32):
 
NTSTATUS
CompletionRoutine_31 (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )
{   

    // 
    // Because the dispatch routine is returning the status of lower driver
    // as is, you must do the following:
    // 
    if (Irp->PendingReturned) {
        
        IoMarkIrpPending( Irp );
    }
    
    return STATUS_CONTINUE_COMPLETION ; // Make sure of same synchronicity 
}

NTSTATUS
CompletionRoutine_32 (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )
{   
    // 
    // Because the dispatch routine is returning the status of lower driver
    // as is, you must do the following:
    // 
    if (Irp->PendingReturned) {
        
        IoMarkIrpPending( Irp );
    }
    
    //    
    // To make sure of the same synchronicity, complete the IRP here.
    // You cannot complete the IRP later in another thread because the 
    // the dispatch routine is returning the status returned by the lower
    // driver as is.
    // 
    IoCompleteRequest( Irp,  IO_NO_INCREMENT);  

    // 
    // Although this is an unusual completion routine that you rarely see,
    // it is discussed here to address all possible ways to handle IRPs.  
    // 
    return STATUS_MORE_PROCESSING_REQUIRED; 
} 

				

Szenario 4: Warteschlange für später oder weiterleiten und wiederverwenden

Verwenden Sie den folgenden Codeausschnitt in einer Situation, in denen der Treiber möchte entweder ein IRPs in die Warteschlange und später verarbeiten oder Weiterleiten IRP an den unteren Treiber und für eine bestimmte Anzahl der Versuche vor dem Abschließen des IRPs wiederverwenden. Die Dispatch-Routine kennzeichnet das IRP ausstehende und STATUS_PENDING zurück, da das IRP später in einem anderen Thread durchgeführt werden soll. Hier ändern Sie die Vervollständigung Routine kann den Status das IRP ggf. (im Gegensatz zu vorherigen Szenario).
NTSTATUS
DispathRoutine_4(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    NTSTATUS status;

    // 
    // You mark the IRP pending if you are intending to queue the IRP
    // and process it later. If you are intending to forward the IRP 
    // directly, use one of the methods discussed earlier in this article.
    // 
    IoMarkIrpPending( Irp );    

    // 
    // For demonstration purposes: this IRP is forwarded to the lower driver.
    // 
    IoCopyCurrentIrpStackLocationToNext(Irp); 

    IoSetCompletionRoutine(Irp,
                           CompletionRoutine_41, // or CompletionRoutine_42
                           NULL,
                           TRUE,
                           TRUE,
                           TRUE
                           ); 
    IoCallDriver(TopOfDeviceStack, Irp);

    // 
    // Because you marked the IRP pending, you must return pending,
    // regardless of the status of returned by IoCallDriver.
    // 
    return STATUS_PENDING ;

}
Abschluss Routine kann entweder zurückgeben, STATUS_CONTINUE_COMPLETION oder STATUS_MORE_PROCESSING_REQUIRED. Sie zurückkehren STATUS_MORE_PROCESSING_REQUIRED nur, wenn Sie möchten, das IRP von einem anderen Thread wiederverwenden und später vervollständigen. NTSTATUS-CompletionRoutine_41
NTSTATUS
CompletionRoutine_41(
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )
{ 
    // 
    // By returning STATUS_CONTINUE_COMPLETION , you are relinquishing the 
    // ownership of the IRP. You cannot touch the IRP after this.
    // 
    return STATUS_CONTINUE_COMPLETION ; 
} 


NTSTATUS
CompletionRoutine_42 (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )
{  
    // 
    // Because you are stopping the completion of the IRP by returning the
    // following status, you must complete the IRP later.
    // 
    return STATUS_MORE_PROCESSING_REQUIRED ; 
} 
				

Szenario 5: Durchführen der IRPs in die Dispatch-routine

Dieses Szenario zeigt eine IRPs in die Dispatch-Routine abzuschließen.

wichtig Wenn Sie eine IRPs in die Dispatch-Routine abgeschlossen haben, sollte der Rückgabestatus der Dispatch-Routine den Status der Wert übereinstimmen, die in der IoStatus Block IRP (-> IoStatus.Status Irp) festgelegt ist.
NTSTATUS
DispatchRoutine_5(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    // 
    // <-- Process the IRP here.
    // 
    Irp->IoStatus.Status = STATUS_XXX;
    Irp->IoStatus.Information = YYY;
    IoCompletRequest(Irp, IO_NO_INCREMENT);
    return STATUS_XXX;
} 

Informationsquellen

Teil 2 dieses Thema ist in der folgenden Knowledge Base enthalten:
326315  (http://support.microsoft.com/kb/326315/ ) Verschiedene Möglichkeiten zum Behandeln von IRPs - betrügen Blatt (Teil 2 von 2)
  • Walter Oney. Programmieren von Windows Driver Model , Second Edition, Kapitel 5.

Die Informationen in diesem Artikel beziehen sich auf:
  • Microsoft Win32 Device Driver Kit for Windows 2000
  • Microsoft Windows XP Driver Development Kit
  • Microsoft Windows Server 2003 Driver Development Kit (DDK)
  • Microsoft Windows NT 4.0
  • the operating system: Microsoft Windows 2000
  • the operating system: Microsoft Windows XP
Keywords: 
kbmt kbinfo kbkmode kbwdm KB320275 KbMtde
Maschinell übersetzter ArtikelMaschinell übersetzter Artikel
Wichtig: Dieser Artikel wurde maschinell und nicht von einem Menschen übersetzt. Die Microsoft Knowledge Base ist sehr umfangreich und ihre Inhalte werden ständig ergänzt beziehungsweise überarbeitet. Um Ihnen dennoch alle Inhalte auf Deutsch anbieten zu können, werden viele Artikel nicht von Menschen, sondern von Übersetzungsprogrammen übersetzt, die kontinuierlich optimiert werden. Doch noch sind maschinell übersetzte Texte in der Regel nicht perfekt, insbesondere hinsichtlich Grammatik und des Einsatzes von Fremdwörtern sowie Fachbegriffen. Microsoft übernimmt keine Gewähr für die sprachliche Qualität oder die technische Richtigkeit der Übersetzungen und ist nicht für Probleme haftbar, die direkt oder indirekt durch Übersetzungsfehler oder die Verwendung der übersetzten Inhalte durch Kunden entstehen könnten.
Den englischen Originalartikel können Sie über folgenden Link abrufen: 320275  (http://support.microsoft.com/kb/320275/en-us/ )
Microsoft stellt Ihnen die in der Knowledge Base angebotenen Artikel und Informationen als Service-Leistung zur Verfügung. Microsoft übernimmt keinerlei Gewährleistung dafür, dass die angebotenen Artikel und Informationen auch in Ihrer Einsatzumgebung die erwünschten Ergebnisse erzielen. Die Entscheidung darüber, ob und in welcher Form Sie die angebotenen Artikel und Informationen nutzen, liegt daher allein bei Ihnen. Mit Ausnahme der gesetzlichen Haftung für Vorsatz ist jede Haftung von Microsoft im Zusammenhang mit Ihrer Nutzung dieser Artikel oder Informationen ausgeschlossen.