24/05/2018, 18:59

Tóm lược các kịch bản xử lý (Summary—Eight IRP-Handling Scenarios)

Mặc dù chiều dài của những giải thích có trước, sự dùng IRP thật sự hoàn toàn dễ dàng. Bởi sự tính của tôi, chỉ có tám kịch bản một cách đáng kể khác nhau thông dụng, và mã được yêu cầu xử lý những kịch bản đó tương đối đơn giản. Trong mục cuối cùng này của ...

Mặc dù chiều dài của những giải thích có trước, sự dùng IRP thật sự hoàn toàn dễ dàng. Bởi sự tính của tôi, chỉ có tám kịch bản một cách đáng kể khác nhau thông dụng, và mã được yêu cầu xử lý những kịch bản đó tương đối đơn giản. Trong mục cuối cùng này của chương này, Tôi tập hợp một số bức tranh và mã lấy mẫu để giúp đỡ bạn sắp xếp lại tất cả kiến thức lý thuyết.

Bởi vì mục này được dự định khi một cookbook mà bạn có thể sử dụng không có việc hoàn toàn hiểu mọi sắc thái cuối cùng, Tôi có bao gồm những sự gọi tới những chức năng khóa loại bỏ mà tôi sẽ tranh luận chi tiết trong Chương 6. Tôi cũng có sử dụng phương pháp tốc ký IoSetCompletionRoutine[Ex ] để chỉ báo những chỗ bạn nên gọi IoSetCompletionRoutineEx, trong một hệ thống ở đâu nó sẵn sàng, thiết đặt một sự hoàn thành thường lệ. Tôi cũng sử dụng một phiên bản quá tải của người giúp đỡ thủ tục CompleteRequest của tôi mà không thay đổi IoStatus. Thông tin trong những ví dụ này vì điều đó đúng cho IRP_MJ_PNP và không phải không đúng cho những kiểu IRP khác.

Kịch bản 1-Sự Chuyển xuống với hoàn thành thủ tục

Trong kịch bản này, người nào đó gửi bạn một IRP. Bạn sẽl đẩy IRP này tới trình điều khiển thấp hơn trong ngăn xếp PnP của các bạn, và bạn sẽ làm sự xử lý sau nào đó trong một sự hoàn thành thường lệ. Xem hình 5-11. Chấp nhận chiến lược này khi tất cả điều sau là đúng:

  • Người nào đó đang gửi bạn một IRP (ngược với bạn tạo ra chính IRP).
  • IRP có lẽ đã đến ở DISPATCH_LEVEL hay trong một luồng chuyên quyền ( Vì thế là bạn không có thể làm trở ngại trong khi những trình điều khiển thấp hơn xử lý IRP).
  • Sự xử lý sau của các bạn có thể được làm ở DISPATCH_LEVEL nếu cần ( Bởi vì những thủ tục hoàn thành có lẽ đã được gọi ở DISPATCH _LEVEL).

Hình 5-11. Sự Chuyển xuống với sự hoàn thành thủ tục .

Sự gởi đi của các bạn và những thủ tục hoàn thành sẽ có mẫu thuộc về bộ khung này:

NTSTATUS DispatchSomething(PDEVICE_OBJECT fdo, PIRP Irp)

  {

  PDEVICE_EXTENSION pdx =

    (PDEVICE_EXTENSION) fdo->DeviceExtension;

  NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);

  if (!NT_SUCCESS(status))

    return CompleteRequest(Irp, status);

  IoCopyCurrentIrpStackLocationToNext(Irp);

  IoSetCompletionRoutine(Irp,

    (PIO_COMPLETION_ROUTINE) CompletionRoutine,

    pdx, TRUE, TRUE, TRUE);

  return IoCallDriver(pdx->LowerDeviceObject, Irp);

  }

NTSTATUS CompletionRoutine(PDEVICE_OBJECT fdo, PIRP Irp,

  PDEVICE_EXTENSION pdx)

  {

  if (Irp->PendingReturned)

    IoMarkIrpPending(Irp);

  <whatever post processing you wanted to do>

  IoReleaseRemoveLock(&pdx->RemoveLock, Irp);

  return STATUS_SUCCESS;

  }

Kịch bản 2-Sự Chuyển xuống không có sự hoàn thành thủ tục

Trong kịch bản này, người nào đó gửi bạn một IRP. Bạn sẽ chuyển tiếp IRP tới trình điều khiển thấp hơn trong chồng PnP của các bạn, nhưng bạn không cần làm bất cứ cái gì với IRP. Xem hình 5-12. Chấp nhận chiến lược này, mà có thể cũng được gọi " Let Mikey try it" cách tiếp cận, khi cả hai của sự theo sau true:

  • Một ai đó đang gửi bạn một IRP (ngược với bạn tạo ra chính IRP).
  • Bạn không xử lý IRP này, trừ phi một trình điều khiển ở dưới bạn có lẽ đã muốn tới.

Hình 5-12. Sự Chuyển xuống không có sự hoàn thành thủ tục .

Kịch bản này thường được sử dụng trong một trình điều khiển lọc, mà cần phải đóng vai một ống dẫn đơn giản cho mọi IRP mà nó không đặc biệt cần lọc.

Tôi khuyến cáo viết thủ tục trợ giúp sau đây, mà bạn có thể sử dụng mỗi khi bạn cần thuê chiến lược này.

NTSTATUS ForwardAndForget(PDEVICE_EXTENSION pdx, PIRP Irp)

  {

  PDEVICE_EXTENSION pdx =

    (PDEVICE_EXTENSION) fdo->DeviceExtension;

  NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);

  if (!NT_SUCCESS(status))

    return CompleteRequest(Irp, status);

  IoSkipCurrentIrpStackLocation (Irp);

  status = IoCallDriver(pdx->LowerDeviceObject, Irp);

  IoReleaseRemoveLock(&pdx->RemoveLock, Irp);

  return status;

  }

Kịch bản 3- Hoàn thành trong thủ tục gởi đi

Trong kịch bản này, bạn ngay lập tức hoàn thành một IRP mà người nào đó gửi bạn. Xem hình 5-13. Chấp nhận chiến lược này khi:

  • Một ai đó đang gửi bạn một IRP (ngược với bạn tạo ra chính IRP), và
  • Bạn có thể xử lý IRP ngay lập tức. Điều này là trường hợp cho nhiều cách thức của những yêu cầu điều khiển (IOCTL) vào/ra. Hoặc
  • Cái gì đó rõ ràng sai với IRP, mà trong đó trường hợp gây ra nó quên ngay lập tức có lẽ đã là thứ tử tế nhất để làm.

Hình 5-13. Hoàn thành trong sự liên lạc thủ tục .

Sự liên lạc thur tục của các bạn có mẫu thuộc về bộ khung này:

NTSTATUS DispatchSomething(PDEVICE_OBJECT fdo, PIRP Irp)

  {

  PDEVICE_EXTENSION pdx =

    (PDEVICE_EXTENSION) fdo->DeviceExtension;

  <process the IRP>

  Irp->IoStatus.Status = STATUS_XXX;

  Irp->IoStatus.Information = YYY;

  IoCompleteRequest(Irp, IO_NO_INCREMENT);

  return STATUS_XXX;

  }

Kịch bản 4-Hàng đợi cho sau này xử lý

Trong kịch bản này, người nào đó gửi bạn một IRP điều đó bạn không có thể xử lý ngay tức thì. Bạn mang IRP vào một hàng đợi cho sau này xử lý ở một thủ tục StartIo. Xem Hình 5-14. Chấp nhận chiến lược này khi cả hai sự theo sau đúng:

  • Người nào đó đang gửi bạn một IRP (ngược với bạn tạo ra chính IRP).
  • Bạn không biết rằng bạn có thể xử lý IRP ngay tức thì. Điều này thường xuyên là trường hợp cho IRPs mà đòi hỏi được xếp theo thứ tự truy nhập phần cứng, như những sự đọc và viết.

Hình 5-14. Hàng đợi cho xử lý sau này .

Mặc dầu bạn có nhiều sự lựa chọn, một cách tiêu biểu của sự thi hành kịch bản này suy ra việc sử dụng một DEVQUEUE để quản lý hàng đợi IRP. Những đoạn sau đây cho thấy những phần khác nhau của một trình điều khiển cho một ngắt vào/ra được chương trình hóa-được điều khiển thiết bị ngắt tương tác như thế nào. Chỉ những phần được cho thấy trong chữ nét đậm liên quan đặc biệt tới sự dùng IRP.

typedef struct _DEVICE_EXTENSION {

  DEVQUEUE dqReadWrite;

  } DEVICE_EXTENSION, *PDEVICE_EXTENSION;

NTSTATUS AddDevice(PDRIVER_OBJECT DriverObject,

  PDEVICE_OBJECT pdo)

  {

  InitializeQueue(&pdx->dqReadWrite, StartIo);

  IoInitializeDpcRequest(fdo, (PIO_DPC_ROUTINE) DpcForIsr);

  }

NTSTATUS DispatchReadWrite(PDEVICE_OBJECT fdo, PIRP Irp)

   {

  PDEVICE_EXTENSION pdx =

    (PDEVICE_EXTENSION) fdo->DeviceExtension;

  IoMarkIrpPending(Irp);

  StartPacket(&pdx->dqReadWrite, fdo, Irp, CancelRoutine);

   return STATUS_PENDING;

  }

VOID CancelRoutine(PDEVICE_OBJECT fdo, PIRP Irp)

  {

  PDEVICE_EXTENSION pdx =

    (PDEVICE_EXTENSION) fdo->DeviceExtension;

  CancelRequest(&pdx->dqReadWrite, Irp);

  }

VOID StartIo(PDEVICE_OBJECT fdo, PIRP Irp)

  {

  }

BOOLEAN OnInterrupt(PKINTERRUPT junk, PDEVICE_EXTENSION pdx)

  {

  PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);

  Irp->IoStatus.Status = STATUS_XXX;

  Irp->IoStatus.Information = YYY;

  IoRequestDpc(pdx->DeviceObject, NULL, pdx);

  }

VOID DpcForIsr(PKDPC junk1, PDEVICE_OBJECT fdo, PIRP junk2,

  PDEVICE_EXTENSION pdx)

  {

  PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);

  StartNextPacket(&pdx->dqReadWrite, fdo);

  IoCompleteRequest(Irp, IO_NO_INCREMENT);

  }

Kịch bản 5-IRP Không đồng bộ của riêng mình

Trong kịch bản này bạn tạo nên một IRP không đồng bộ, bạn tiếp tới trình điều khiển khác. Xem Hình 5-15. Chấp nhận chiến lược này khi những điều kiện sau đây đúng:

  • Bạn cần trình điều khiển khác để thực hiện một thao tác trên lợi ích của các bạn.
  • Hay là bạn trong một luồng chuyên quyền ( bạn không quyết tâm Block) hay bạn chạy ở DISPATCH_LEVEL (trong trường hợp nào bạn không có thể block).

Hình 5-15. IRP không đồng bộ của riêng mình .

Bạn sẽ có mã như sau trong trình điều khiển của các bạn. Điều này không chiến thắng tất yếu trong một sự liên lạc thủ tục IRP, và đối tượng thiết bị đích không được chiến thắng tất yếu là tiếp theo thấp hơn một trong ngăn xếp PnP của các bạn. Nhìn vào tài liệu DDK cho những chi tiết đầy đủ về gọi IoBuildAsynchronousFsdRequest và IoAllocateIrp như thế nào.

SOMETYPE SomeFunction(PDEVICE_EXTENSION pdx,

  PDEVICE_OBJECT DeviceObject)

  {

  NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock,

    (PVOID) 42);

  if (!NT_SUCCESS(status))

    return <status>;

  PIRP Irp;

  Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_XXX, DeviceObject,

    ...);

    -or-

  Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);

  PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);

  stack->MajorFunction = IRP_MJ_XXX;

  <additional initialization)

  IoSetCompletionRoutine[Ex]([pdx->DeviceObject,] Irp, 

    (PIO_COMPLETION_ROUTINE) CompletionRoutine, pdx,

    TRUE, TRUE, TRUE);

  ObReferenceObject(DeviceObject);

  IoCallDriver(DeviceObject, Irp);

  ObDereferenceObject(DeviceObject);

  }

NTSTATUS CompletionRoutine(PDEVICE_OBJECT junk, PIRP Irp,

  PDEVICE_EXTENSION pdx)

  {

  <IRP cleanup -- see below>

  IoFreeIrp(Irp);

  IoReleaseRemoveLock(&pdx->RemoveLock, (PVOID) 42);

  return STATUS_MORE_PROCESSING_REQUIRED;

  }

Những sự gọi tới IoAcquireRemoveLock và IoReleaseRemoveLock (những điểm được gắn nhãn A) chỉ cần thiết nếu thiết bị tới nào bạn gửi IRP này là LowerDeviceObject trong ngăn xếp PnP của các bạn. 42 là một nhãn chuyên quyền-nó là hoàn toàn phức tạp để cố gắng gỡ bỏ sự khóa sau những tồn tại IRP, đúng như vậy chúng tôi có thể sử dụng con trỏ IRP như một nhãn gỡ lỗi xây dựng.

Những sự gọi ObReferenceObject và ObDereferenceObject mà đi trước và đi theo sau sự gọi IoCallDriver (những điểm được gắn nhãn B) chỉ cần thiết khi nào bạn đã sử dụng IoGetDeviceObjectPointer để thu được con trỏ DeviceObject và khi sự hoàn thành tảu tục ( hay cái gì đó nó gọi) sẽ giải phóng sự tham khảo kết quả tới một đối tượng thiết bị hay tệp tin.

Bạn không có cả hai mã A và mã B-bạn có một tập hợp hay không cái nào.

Nếu bạn sử dụng IoBuildAsynchronousFsdRequest để xây dựng một IRP_MJ_READ HayIRP _MJ_WRITE, bạn có một vài cleanup tương đối phức tạp nào đó để thực hiện trong sự hoàn thành thủ tục.

Cleanup cho DO_DIRECT_IO đích (C leanup for DO_DIRECT_IO Target ):

Nếu đối tượng thiết bị đích chỉ báo phương pháp đệm DO_DIRECT_IO bạn sẽ phải giải phóng những danh sách bộ mô tả kí ức mà quản lý vào/ra cấp phát cho bộ đệm dữ liệu của các bạn:

NTSTATUS CompletionRoutine(...)

  {

  PMDL mdl;

  while ((mdl = Irp->MdlAddress))

    {

    Irp->MdlAddress = mdl->Next;

    MmUnlockPages(mdl); // <== only if you earlier

                        // called MmProbeAndLockPages

    IoFreeMdl(mdl);

    }

  IoFreeIrp(Irp);

  <optional release of remove lock>

  return STATUS_MORE_PROCESSING_REQUIRED;

  }

Cleanup cho DO_BUFFERED_IO đích ( Cleanup for DO_BUFFERED_IO Target ):

Nếu đối tượng thiết bị đích chỉ báo DO_BUFFERED_IO , quản lý vào/ra sẽ tạo ra một bộ đệm hệ thống. Sự hoàn thành thủ tục của các bạn về mặt lý thuyết cần phải sao chép dữ liệu từ bộ đệm hệ thống đến bộ đệm của riêng mình và sau đó giải phóng bộ đệm hệ thống. Không may, những bit cờ hiệu và những lĩnh vực được cần để làm điều này thì không phải được lấy tài liệu trong DDK. Lời khuyên của tôi trực tiếp sẽ đơn giản không gửi những sự đọc và viết tới một trình điều khiển mà sử dụng bộ đệm vào/ra. Thay vào đó, gọi ZwReadFile hay ZwWriteFile.

Cleanup cho những đích khác (C leanup for Other Targets ):

Nếu thiết bị đích chỉ báo không DO_DIRECT_IO hay DO_BUFFERED_IO, không có cleanup bổ sung. Phew!

Kịch bản 6-IRP đồng bộ của riêng mình

Trong kịch bản này bạn tạo nên một đồng bộ IRP, bạn chuyển tiếp tới trình điều khiển khác. Xem hình 5-16. Chấp nhận chiến lược này khi tất cả sự theo sau đúng:

  • Bạn cần trình điều khiển khác để thực hiện một thao tác trên sự đại diện của các bạn.
  • Bạn phải đợi thao tác để hoàn thành trước đây theo đuổi.
  • Bạn chạy ở PASSIVE_LEVEL trong một luồng không chuyên quyền.

Hình 5-16. IRP đồng bộ của riêng mình .

Bạn sẽ có mã như sự theo sau trong trình điều khiển của) các bạn. Điều này không chiến thắng tất yếu trong một sự liên lạc thủ tục IRP, và đối tượng thiết bị đích không được chiến thắng tất yếu là tiếp theo thấp hơn một trong ngăn xếp PnP của các bạn. Nhìn vào tài liệu DDK cho những chi tiết đầy đủ về gọi IoBuildSynchronousFsdRequest và IoBuildDeviceIoControlRequest như thế nào.

SOMETYPE SomeFunction(PDEVICE_EXTENSION pdx,

  PDEVICE_OBJECT DeviceObject)

  {

  NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock,

    (PVOID) 42);

  if (!NT_SUCCESS(status))

    return <status>;

  PIRP Irp;

  KEVENT event;

  IO_STATUS_BLOCK iosb;

  KeInitializeEvent(&event, NotificationEvent, FALSE);

  Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_XXX,

    DeviceObject, ..., &event, &iosb);

    -or-

  Irp = IoBuildDeviceIoControlRequest(IOCTL_XXX, DeviceObject,

    ..., &event, &iosb);

  status = IoCallDriver(DeviceObject, Irp);

  if (status == STATUS_PENDING)

    {

    KeWaitForSingleObject(&event, Executive, KernelMode,

      FALSE, NULL);

    status = iosb.Status;

    }

  IoReleaseRemoveLock(&pdx->RemoveLock, (PVOID) 42);

  }

Như trong kịch bản 5, những sự gọi tới IoAcquireRemoveLock và IoReleaseRemoveLock (những điểm được gắn nhãn A) chỉ cần thiết nếu thiết bị tới nào bạn gửi IRP này là LowerDeviceObject trong ngăn xếp PnP của các bạn. 42 là một nhãn chuyên quyền-nó đơn giản quá phức tạp để thử để thu nhận sự khóa loại bỏ sau tồn tại IRP, đúng như vậy chúng tôi có thể sử dụng con trỏ IRP như một nhãn gỡ lỗi xây dựng.

Chúng tôi sẽ sử dụng kịch bản này thường xuyên trong Chương 12 để gửi những khối yêu cầu USB (URBs) đồng bộ xuống ngawn xếp. Trong những ví dụ chúng tôi sẽ nghiên cứu ở đó, chúng tôi sẽ thường đang làm điều này trong văn cảnh của một sự liên lạc thủ tục IRP mà độc lập thu nhận sự khóa loại bỏ. Bởi vậy, bạn không chiến thắng nhìn thấy mã khóa loại bỏ thêm trong những ví dụ đó.

Bạn không phải làm quét dọn sau khi IRP này! Quản lý vào/ra làm nó tự động.

Kịch bản 7-Sự Chuyển qua Đồng bộ Xuống

In kịch bản này, người nào đó gửi bạn một IRP. Bạn đi qua IRP xuống đồng bộ trong ngăn xếp PnP của các bạn và sau đó tiếp tục xử lý. Xem hình 5-17. Chấp nhận chiến lược này khi tất cả sự theo sau đúng:

  • Người nào đó đang gửi bạn một IRP (ngược với bạn tạo ra chính IRP).
  • Bạn chạy ở PASSIVE_LEVEL trong một luồng không chuyên quyền.
  • Sự xử lý sau của các bạn cho IRP phải được làm ở PASSIVE_LEVEL.

Hình 5-17. Sự chuyển qua Đồng bộ xuống .

Một ví dụ tốt của khi nào bạn cần sử dụng chiến lược này trong khi đang xử lý một hương vị(flavor)IRP_MN_START_DEVICE của yêu cầu PnP.

Tôi khuyến cáo viết hai thủ tục giúp đỡ để làm cho nó trở nên dễ dàng thực hiện sự chuyển qua đồng bộ này- thao tác xuống:

NTSTATUS ForwardAndWait(PDEVICE_EXTENSION pdx, PIRP Irp)

  {

  KEVENT event;

  KeInitialize(&event, NotificationRoutine, FALSE);

  IoCopyCurrentIrpStackLocationToNext(Irp);

  IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)

    ForwardAndWaitCompletionRoutine, &event, TRUE, TRUE, TRUE);

  NTSTATUS status = IoCallDriver(pdx->LowerDeviceObject, Irp);

  if (status == STATUS_PENDING)

    {

    KeWaitForSingleObject(&event, Executive, KernelMode,

      FALSE, NULL);

    status = Irp->IoStatus.Status;

    }

  return status;

  }

NTSTATUS ForwardAndWaitCompletionRoutine(PDEVICE_OBJECT fdo,

  PIRP Irp, PKEVENT pev)

  {

  if (Irp->PendingReturned)

    KeSetEvent(pev, IO_NO_INCREMENT, FALSE);

  return STATUS_MORE_PROCESSING_REQUIRED;

  }

Người gọi thủ tục này cần gọi cho IoCompleteRequest cho IRP này và để thu nhận và giải phóng sự khóa loại bỏ. Nó không thích hợp cho ForwardAndWait để chứa đựng khóa lôgic loại bỏ bởi vì người gọi có lẽ đã không muốn giải phóng sự khóa sớm như vậy.

Chú ý rằng chức năng IoForwardIrpSynchronously Windows XP DDK đóng gói đây giống như những bước.

Kịch bản 8-IRP Không đồng bộ được xử lý đồng bộ

In kịch bản này, bạn tạo nên một IRP không đồng bộ, bạn chuyển tiếp tới trình điều khiển khác. Rồi bạn đợi IRP để hoàn thành. Xem hình 5-18. Chấp nhận chiến lược này khi tất cả sự theo sau đúng:

  • Bạn cần trình điều khiển khác để thực hiện một thao tác trên sự đại diện của các bạn.
  • Bạn cần đợi thao tác để kết thúc trước khi bạn có thể tiếp tục.
  • Bạn chạy ở APC_LEVEL trong một luồng không chuyên quyền.

Hình 5-18. IRP không đồng bộ được xử lý đồng bộ .

Tôi sử dụng kỹ thuật này khi nào tôi mắc phải một mutex nhanh thực hiện và cần thực hiện một thao tác đồng bộ. Mã của các bạn kết hợp những phần tử bạn nhìn thấy trước đây (so sánh với những kịch bản 5 và 7):

SOMETYPE SomeFunction(PDEVICE_EXTENSION pdx,

  PDEVICE_OBJECT DeviceObject)

  {

  NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock,

    (PVOID) 42);

  if (!NT_SUCCESS(status))

    return <status>;

  PIRP Irp;

  Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_XXX, DeviceObject,

    ...);

    -or-

  Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);

  PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);

  Stack->MajorFunction = IRP_MJ_XXX;

  <additional initialization)

  KEVENT event;

  KeInitializeEvent(&event, NotificationEvent, FALSE);

  IoSetCompletionRoutine[Ex]([pdx->DeviceObject], Irp,

    (PIO_COMPLETION_ROUTINE) CompletionRoutine,

    &event, TRUE, TRUE, TRUE);

  status = IoCallDriver(DeviceObject, Irp);

  if (status == STATUS_PENDING)

    KeWaitForSingleObject(&event, Executive, KernelMode,

    FALSE, NULL);

  IoReleaseRemoveLock(&pdx->RemoveLock, (PVOID) 42);

  }

NTSTATUS CompletionRoutine(PDEVICE_OBJECT junk, PIRP Irp,

  PKEVENT pev)

  {

  if (Irp->PendingReturned)

    KeSetEvent(pev, EVENT_INCREMENT, FALSE);

  <IRP cleanup -- see above>

  IoFreeIrp(Irp);

  return STATUS_MORE_PROCESSING_REQUIRED;

  }

(những điểm được gắn nhãn A) chỉ cần thiết nếu thiết bị tới đó bạn đang gửi IRP này

Như trong những kịch bản trước đó, những sự gọi tới IoAcquireRemoveLock và IoReleaseưRemoveLock (những điểm được gắn nhãn A) chỉ cần thiết nếu thiết bị tới nào bạn gửi IRP này là LowerDeviceObject trong ngăn xếp PnP của các bạn. 42 là một nhãn chuyên quyền-nó đơn giản quá phức tạp để thử để thu nhận sự khóa loại bỏ sau tồn tại IRP, đúng như vậy chúng tôi có thể sử dụng con trỏ IRP như một nhãn gỡ lỗi xây dựng.

Chú ý rằng bạn vẫn còn phải thực hiện tất cả cùng cleanup được bàn luận trước đó vì Quản lý vào/ra là không quét dọn sau khi một IRP không đồng bộ. Bạn có lẽ đã cũng cần cung cấp cho cancelling IRP này, tại trường hợp nào bạn cần phải sử dụng kỹ thuật tranh luận trong thân của chương này cho IRPs không đồng bộ cancelling.

0