Leaked source code of windows server 2003
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.

223 lines
7.1 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. rxtdi.c
  5. Abstract:
  6. This module implements the NT specific notification routines in the connection engine
  7. Revision History:
  8. Balan Sethu Raman [SethuR] 15-Feb-1995
  9. Notes:
  10. The notification of a transport binding/unbinding to the mini redirectors is done
  11. in a worker thread. In order to simplify the task of writing a routine the connection
  12. engine guarantees that not more than one invocation of MRxTranspotrtUpdateHandler
  13. will be active at any instant of time for a given mini redirector.
  14. There is no thread dedicated to processing these notifications. A worker thread is
  15. used to process the notifications. In order to ensure condition (1) all the notifications
  16. are queued ( interlocked queue ).
  17. --*/
  18. #include "precomp.h"
  19. #pragma hdrstop
  20. #include "mrx.h"
  21. typedef struct _RXCE_MINIRDR_NOTIFICATION_CONTEXT_ {
  22. LIST_ENTRY NotificationListEntry;
  23. PRXCE_TRANSPORT pTransport;
  24. RXCE_TRANSPORT_EVENT TransportEvent;
  25. } RXCE_MINIRDR_NOTIFICATION_CONTEXT,
  26. *PRXCE_MINIRDR_NOTIFICATION_CONTEXT;
  27. typedef struct _RXCE_MINIRDR_NOTIFICATION_HANDLER_ {
  28. WORK_QUEUE_ITEM WorkQueueEntry;
  29. KSPIN_LOCK Lock;
  30. LIST_ENTRY ListHead;
  31. BOOLEAN NotifierActive;
  32. } RXCE_MINIRDR_NOTIFICATION_HANDLER,
  33. *PRXCE_MINIRDR_NOTIFICATION_HANDLER;
  34. RXCE_MINIRDR_NOTIFICATION_HANDLER s_RxCeMinirdrNotificationHandler;
  35. extern VOID
  36. MiniRedirectorsNotifier(
  37. PVOID NotificationContext);
  38. NTSTATUS
  39. InitializeMiniRedirectorNotifier()
  40. {
  41. s_RxCeMinirdrNotificationHandler.NotifierActive = FALSE;
  42. KeInitializeSpinLock(&s_RxCeMinirdrNotificationHandler.Lock);
  43. InitializeListHead(&s_RxCeMinirdrNotificationHandler.ListHead);
  44. return STATUS_SUCCESS;
  45. }
  46. NTSTATUS
  47. NotifyMiniRedirectors(
  48. RXCE_TRANSPORT_HANDLE hTransport,
  49. RXCE_TRANSPORT_EVENT TransportEvent,
  50. RXCE_NOTIFICATION_MODE Mode)
  51. {
  52. NTSTATUS Status;
  53. KIRQL SavedIrql;
  54. PRXCE_MINIRDR_NOTIFICATION_CONTEXT pContext;
  55. pContext = RxAllocatePoolWithTag(
  56. PagedPool | POOL_COLD_ALLOCATION,
  57. sizeof(RXCE_MINIRDR_NOTIFICATION_CONTEXT),
  58. RX_MISC_POOLTAG);
  59. if (pContext != NULL) {
  60. pContext->TransportEvent = TransportEvent;
  61. // Reference the transport entry
  62. pContext->pTransport = RxCeReferenceTransport(hTransport);
  63. if (Mode == RXCE_ASYNCHRONOUS_NOTIFICATION) {
  64. BOOLEAN DispatchNotifier;
  65. // Acquire the spin lock ...
  66. KeAcquireSpinLock(
  67. &s_RxCeMinirdrNotificationHandler.Lock,
  68. &SavedIrql);
  69. DispatchNotifier = (IsListEmpty(&s_RxCeMinirdrNotificationHandler.ListHead) &&
  70. !s_RxCeMinirdrNotificationHandler.NotifierActive);
  71. InsertTailList(&s_RxCeMinirdrNotificationHandler.ListHead,&pContext->NotificationListEntry);
  72. if (DispatchNotifier) {
  73. s_RxCeMinirdrNotificationHandler.NotifierActive = TRUE;
  74. }
  75. // Release the spin lock
  76. KeReleaseSpinLock(
  77. &s_RxCeMinirdrNotificationHandler.Lock,
  78. SavedIrql);
  79. // If the notification list is empty a worker thread needs to be fired up.
  80. if (DispatchNotifier) {
  81. RxPostToWorkerThread(
  82. CriticalWorkQueue,
  83. &s_RxCeMinirdrNotificationHandler.WorkQueueEntry,
  84. MiniRedirectorsNotifier,
  85. &s_RxCeMinirdrNotificationHandler);
  86. }
  87. Status = STATUS_SUCCESS;
  88. } else {
  89. ULONG i;
  90. PMRX_TRANSPORT_UPDATE_HANDLER MRxTransportUpdateHandler;
  91. PLIST_ENTRY ListEntry;
  92. // Notify all the mini redirectors ....
  93. for (ListEntry = RxRegisteredMiniRdrs.Flink;
  94. ListEntry!= &RxRegisteredMiniRdrs;
  95. ListEntry = ListEntry->Flink) {
  96. PRDBSS_DEVICE_OBJECT RxDeviceObject = CONTAINING_RECORD( ListEntry, RDBSS_DEVICE_OBJECT, MiniRdrListLinks );
  97. MRxTransportUpdateHandler = RxDeviceObject->Dispatch->MRxTransportUpdateHandler;
  98. if ( MRxTransportUpdateHandler != NULL) {
  99. Status = MRxTransportUpdateHandler(
  100. pContext->pTransport,
  101. pContext->TransportEvent,
  102. pContext->pTransport->pProviderInfo);
  103. }
  104. }
  105. // Derefrence the transport entry
  106. RxCeDereferenceTransport(pContext->pTransport);
  107. // free the notification context.
  108. RxFreePool(pContext);
  109. Status = STATUS_SUCCESS;
  110. }
  111. } else {
  112. Status = STATUS_INSUFFICIENT_RESOURCES;
  113. }
  114. return Status;
  115. }
  116. VOID
  117. MiniRedirectorsNotifier(
  118. PVOID NotificationContext)
  119. {
  120. NTSTATUS Status;
  121. KIRQL SavedIrql;
  122. PLIST_ENTRY pEntry;
  123. PRXCE_MINIRDR_NOTIFICATION_CONTEXT pContext;
  124. PMRX_TRANSPORT_UPDATE_HANDLER MRxTransportUpdateHandler;
  125. for (;;) {
  126. PLIST_ENTRY ListEntry;
  127. // Acquire the spin lock ...
  128. KeAcquireSpinLock(
  129. &s_RxCeMinirdrNotificationHandler.Lock,
  130. &SavedIrql);
  131. // Remove an item from the notification list.
  132. if (!IsListEmpty(&s_RxCeMinirdrNotificationHandler.ListHead)) {
  133. pEntry = RemoveHeadList(
  134. &s_RxCeMinirdrNotificationHandler.ListHead);
  135. } else {
  136. pEntry = NULL;
  137. s_RxCeMinirdrNotificationHandler.NotifierActive = FALSE;
  138. }
  139. // Release the spin lock
  140. KeReleaseSpinLock(&s_RxCeMinirdrNotificationHandler.Lock,SavedIrql);
  141. if (pEntry == NULL) {
  142. break;
  143. }
  144. pContext = (PRXCE_MINIRDR_NOTIFICATION_CONTEXT)
  145. CONTAINING_RECORD(
  146. pEntry,
  147. RXCE_MINIRDR_NOTIFICATION_CONTEXT,
  148. NotificationListEntry);
  149. // Notify all the mini redirectors ....
  150. for (ListEntry = RxRegisteredMiniRdrs.Flink;
  151. ListEntry!= &RxRegisteredMiniRdrs;
  152. ListEntry = ListEntry->Flink) {
  153. PRDBSS_DEVICE_OBJECT RxDeviceObject = CONTAINING_RECORD( ListEntry, RDBSS_DEVICE_OBJECT, MiniRdrListLinks );
  154. MRxTransportUpdateHandler = RxDeviceObject->Dispatch->MRxTransportUpdateHandler;
  155. if ( MRxTransportUpdateHandler != NULL) {
  156. Status = MRxTransportUpdateHandler(
  157. pContext->pTransport,
  158. pContext->TransportEvent,
  159. pContext->pTransport->pProviderInfo);
  160. if (!NT_SUCCESS(Status)) {
  161. }
  162. }
  163. }
  164. // Derefrence the transport entry
  165. RxCeDereferenceTransport(pContext->pTransport);
  166. // free the notification context.
  167. RxFreePool(pContext);
  168. }
  169. }
  170.