Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
3.6 KiB

  1. /*
  2. * UNIMODEM "Fakemodem" controllerless driver illustrative example
  3. *
  4. * (C) 2000 Microsoft Corporation
  5. * All Rights Reserved
  6. *
  7. */
  8. #include "fakemodem.h"
  9. NTSTATUS
  10. CheckStateAndAddReference(
  11. PDEVICE_OBJECT DeviceObject,
  12. PIRP Irp
  13. )
  14. {
  15. PDEVICE_EXTENSION DeviceExtension=(PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  16. KIRQL OldIrql;
  17. BOOLEAN DriverReady;
  18. InterlockedIncrement(&DeviceExtension->ReferenceCount);
  19. DriverReady=(!DeviceExtension->Removing) && (DeviceExtension->Started);
  20. if (!DriverReady) {
  21. //
  22. // driver not accepting requests
  23. //
  24. RemoveReferenceAndCompleteRequest( DeviceObject, Irp,
  25. STATUS_UNSUCCESSFUL);
  26. return STATUS_UNSUCCESSFUL;
  27. }
  28. InterlockedIncrement(&DeviceExtension->ReferenceCount);
  29. return STATUS_SUCCESS;
  30. }
  31. VOID
  32. RemoveReferenceAndCompleteRequest(
  33. PDEVICE_OBJECT DeviceObject,
  34. PIRP Irp,
  35. NTSTATUS StatusToReturn
  36. )
  37. {
  38. PDEVICE_EXTENSION DeviceExtension=(PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  39. KIRQL OldIrql;
  40. LONG NewReferenceCount;
  41. NewReferenceCount=InterlockedDecrement(&DeviceExtension->ReferenceCount);
  42. if (NewReferenceCount == 0) {
  43. //
  44. // device is being removed, set event
  45. //
  46. ASSERT(DeviceExtension->Removing);
  47. D_PNP(DbgPrint("FAKEMODEM: RemoveReferenceAndCompleteRequest: setting event\n");)
  48. KeSetEvent( &DeviceExtension->RemoveEvent, 0, FALSE);
  49. }
  50. Irp->IoStatus.Status = StatusToReturn;
  51. IoCompleteRequest( Irp, IO_SERIAL_INCREMENT);
  52. return;
  53. }
  54. VOID
  55. RemoveReference(
  56. PDEVICE_OBJECT DeviceObject
  57. )
  58. {
  59. PDEVICE_EXTENSION DeviceExtension=(PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  60. LONG NewReferenceCount;
  61. NewReferenceCount=InterlockedDecrement(&DeviceExtension->ReferenceCount);
  62. D_TRACE(
  63. if (DeviceExtension->Removing) {DbgPrint("FAKEMODEM: RemoveReference: %d\n",NewReferenceCount);}
  64. )
  65. if (NewReferenceCount == 0) {
  66. //
  67. // device is being removed, set event
  68. //
  69. ASSERT(DeviceExtension->Removing);
  70. D_PNP(DbgPrint("FAKEMODEM: RemoveReference: setting event\n");)
  71. KeSetEvent( &DeviceExtension->RemoveEvent, 0, FALSE);
  72. }
  73. return;
  74. }
  75. VOID
  76. FakeModemKillAllReadsOrWrites(
  77. IN PDEVICE_OBJECT DeviceObject,
  78. IN PLIST_ENTRY QueueToClean,
  79. IN PIRP *CurrentOpIrp
  80. )
  81. {
  82. KIRQL cancelIrql;
  83. PDRIVER_CANCEL cancelRoutine;
  84. IoAcquireCancelSpinLock(&cancelIrql);
  85. while (!IsListEmpty(QueueToClean))
  86. {
  87. PIRP currentLastIrp = CONTAINING_RECORD(
  88. QueueToClean->Blink, IRP, Tail.Overlay.ListEntry);
  89. RemoveEntryList(QueueToClean->Blink);
  90. cancelRoutine = currentLastIrp->CancelRoutine;
  91. currentLastIrp->CancelIrql = cancelIrql;
  92. currentLastIrp->CancelRoutine = NULL;
  93. currentLastIrp->Cancel = TRUE;
  94. cancelRoutine( DeviceObject, currentLastIrp);
  95. IoAcquireCancelSpinLock(&cancelIrql);
  96. }
  97. if (*CurrentOpIrp)
  98. {
  99. cancelRoutine = (*CurrentOpIrp)->CancelRoutine;
  100. (*CurrentOpIrp)->Cancel = TRUE;
  101. if (cancelRoutine)
  102. {
  103. (*CurrentOpIrp)->CancelRoutine = NULL;
  104. (*CurrentOpIrp)->CancelIrql = cancelIrql;
  105. cancelRoutine( DeviceObject, *CurrentOpIrp);
  106. } else
  107. {
  108. IoReleaseCancelSpinLock(cancelIrql);
  109. }
  110. } else
  111. {
  112. IoReleaseCancelSpinLock(cancelIrql);
  113. }
  114. }