Zugreifen auf Benutzerpuffer in einer Rückrufroutine vor der Operation
Die Voroperationsrückrufroutine eines Minifiltertreibers sollte einen Puffer in einem IRP-basierten E/A-Vorgang wie folgt behandeln:
Überprüfen Sie, ob für den Puffer eine MDL vorhanden ist. Der MDL-Zeiger befindet sich im Parameter MdlAddress oder OutputMdlAddress im FLT_PARAMETERS für den Vorgang. Minifiltertreiber können FltDecodeParameters aufrufen, um den MDL-Zeiger abzufragen.
Eine Methode zum Abrufen einer gültigen MDL besteht darin, im MinorFunction-Member des E/A-Parameterblocks, FLT_IO_PARAMETER_BLOCK, in den Rückrufdaten nach dem flag IRP_MN_MDL zu suchen. Im folgenden Beispiel wird gezeigt, wie Sie nach dem flag IRP_MN_MDL suchen.
NTSTATUS status; PMDL *ReadMdl = NULL; PVOID ReadAddress = NULL; if (FlagOn(CallbackData->Iopb->MinorFunction, IRP_MN_MDL)) { ReadMdl = &CallbackData->Iopb->Parameters.Read.MdlAddress; }
Das IRP_MN_MDL-Flag kann jedoch nur für Lese- und Schreibvorgänge festgelegt werden. Es ist am besten, FltDecodeParameters zum Abrufen einer MDL zu verwenden, da die Routine auf eine gültige MDL für jeden Vorgang überprüft. Im folgenden Beispiel wird nur der MDL-Parameter zurückgegeben, wenn er gültig ist.
NTSTATUS status; PMDL *ReadMdl = NULL; PVOID ReadAddress = NULL; status = FltDecodeParameters(CallbackData, &ReadMdl, NULL, NULL, NULL);
Wenn für den Puffer eine MDL vorhanden ist, rufen Sie MmGetSystemAddressForMdlSafe auf, um die Systemadresse für den Puffer zu erhalten, und verwenden Sie diese Adresse dann für den Zugriff auf den Puffer.
Ausgehend vom vorherigen Beispiel ruft der folgende Code die Systemadresse ab.
if (*ReadMdl != NULL) { ReadAddress = MmGetSystemAddressForMdlSafe(*ReadMdl, NormalPagePriority); if (ReadAddress == NULL) { CallbackData->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; CallbackData->IoStatus.Information = 0; } }
Wenn keine MDL für den Puffer vorhanden ist, verwenden Sie die Pufferadresse, um auf den Puffer zuzugreifen. Um sicherzustellen, dass eine Pufferadresse für den Benutzerbereich gültig ist, muss der Minifiltertreiber eine Routine wie ProbeForRead oder ProbeForWrite verwenden und alle Pufferverweiseaußer Blöcken in try/ einschließen.
Eine Voraboperationsrückrufroutine sollte einen Puffer in einem schnellen E/A-Vorgang wie folgt behandeln:
Verwenden Sie die Pufferadresse, um auf den Puffer zuzugreifen (da ein schneller E/A-Vorgang keine MDL haben kann).
Um sicherzustellen, dass eine Pufferadresse für den Benutzerbereich gültig ist, muss der Minifiltertreiber eine Routine wie ProbeForRead oder ProbeForWrite verwenden und alle Pufferverweiseaußer Blöcken in try/ einschließen.
Für Vorgänge, die schnelle E/A- oder IRP-basiert sein können, sollten alle Pufferverweise mitAusnahme von Blöcken in try/ eingeschlossen werden. Obwohl Sie diese Verweise nicht für IRP-basierte Vorgänge einschließen müssen, die gepufferte E/A verwenden, stellen die Try-Blöcke/ eine sichere Vorsichtsmaßnahme dar.