224 lines
6.9 KiB
C
224 lines
6.9 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
rxtdi.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the NT specific notification routines in the connection engine
|
||
|
||
Revision History:
|
||
|
||
Balan Sethu Raman [SethuR] 15-Feb-1995
|
||
|
||
Notes:
|
||
|
||
The notification of a transport binding/unbinding to the mini redirectors is done
|
||
in a worker thread. In order to simplify the task of writing a routine the connection
|
||
engine guarantees that not more than one invocation of MRxTranspotrtUpdateHandler
|
||
will be active at any instant of time for a given mini redirector.
|
||
|
||
There is no thread dedicated to processing these notifications. A worker thread is
|
||
used to process the notifications. In order to ensure condition (1) all the notifications
|
||
are queued ( interlocked queue ).
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
|
||
#include "mrx.h"
|
||
|
||
typedef struct _RXCE_MINIRDR_NOTIFICATION_CONTEXT_ {
|
||
LIST_ENTRY NotificationListEntry;
|
||
PRXCE_TRANSPORT pTransport;
|
||
RXCE_TRANSPORT_EVENT TransportEvent;
|
||
} RXCE_MINIRDR_NOTIFICATION_CONTEXT,
|
||
*PRXCE_MINIRDR_NOTIFICATION_CONTEXT;
|
||
|
||
typedef struct _RXCE_MINIRDR_NOTIFICATION_HANDLER_ {
|
||
WORK_QUEUE_ITEM WorkQueueEntry;
|
||
KSPIN_LOCK Lock;
|
||
LIST_ENTRY ListHead;
|
||
BOOLEAN NotifierActive;
|
||
} RXCE_MINIRDR_NOTIFICATION_HANDLER,
|
||
*PRXCE_MINIRDR_NOTIFICATION_HANDLER;
|
||
|
||
RXCE_MINIRDR_NOTIFICATION_HANDLER s_RxCeMinirdrNotificationHandler;
|
||
|
||
extern VOID
|
||
MiniRedirectorsNotifier(
|
||
PVOID NotificationContext);
|
||
|
||
NTSTATUS
|
||
InitializeMiniRedirectorNotifier()
|
||
{
|
||
s_RxCeMinirdrNotificationHandler.NotifierActive = FALSE;
|
||
KeInitializeSpinLock(&s_RxCeMinirdrNotificationHandler.Lock);
|
||
InitializeListHead(&s_RxCeMinirdrNotificationHandler.ListHead);
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
NTSTATUS
|
||
NotifyMiniRedirectors(
|
||
RXCE_TRANSPORT_HANDLE hTransport,
|
||
RXCE_TRANSPORT_EVENT TransportEvent,
|
||
RXCE_NOTIFICATION_MODE Mode)
|
||
{
|
||
NTSTATUS Status;
|
||
KIRQL SavedIrql;
|
||
|
||
PRXCE_MINIRDR_NOTIFICATION_CONTEXT pContext;
|
||
|
||
pContext = RxAllocatePoolWithTag(
|
||
PagedPool | POOL_COLD_ALLOCATION,
|
||
sizeof(RXCE_MINIRDR_NOTIFICATION_CONTEXT),
|
||
RX_MISC_POOLTAG);
|
||
|
||
if (pContext != NULL) {
|
||
pContext->TransportEvent = TransportEvent;
|
||
|
||
// Reference the transport entry
|
||
pContext->pTransport = RxCeReferenceTransport(hTransport);
|
||
|
||
if (Mode == RXCE_ASYNCHRONOUS_NOTIFICATION) {
|
||
BOOLEAN DispatchNotifier;
|
||
|
||
// Acquire the spin lock ...
|
||
KeAcquireSpinLock(
|
||
&s_RxCeMinirdrNotificationHandler.Lock,
|
||
&SavedIrql);
|
||
|
||
DispatchNotifier = (IsListEmpty(&s_RxCeMinirdrNotificationHandler.ListHead) &&
|
||
!s_RxCeMinirdrNotificationHandler.NotifierActive);
|
||
|
||
InsertTailList(&s_RxCeMinirdrNotificationHandler.ListHead,&pContext->NotificationListEntry);
|
||
|
||
if (DispatchNotifier) {
|
||
s_RxCeMinirdrNotificationHandler.NotifierActive = TRUE;
|
||
}
|
||
|
||
// Release the spin lock
|
||
KeReleaseSpinLock(
|
||
&s_RxCeMinirdrNotificationHandler.Lock,
|
||
SavedIrql);
|
||
|
||
// If the notification list is empty a worker thread needs to be fired up.
|
||
if (DispatchNotifier) {
|
||
RxPostToWorkerThread(
|
||
CriticalWorkQueue,
|
||
&s_RxCeMinirdrNotificationHandler.WorkQueueEntry,
|
||
MiniRedirectorsNotifier,
|
||
&s_RxCeMinirdrNotificationHandler);
|
||
}
|
||
|
||
Status = STATUS_SUCCESS;
|
||
} else {
|
||
ULONG i;
|
||
PMRX_TRANSPORT_UPDATE_HANDLER MRxTransportUpdateHandler;
|
||
PLIST_ENTRY ListEntry;
|
||
|
||
// Notify all the mini redirectors ....
|
||
for (ListEntry = RxRegisteredMiniRdrs.Flink;
|
||
ListEntry!= &RxRegisteredMiniRdrs;
|
||
ListEntry = ListEntry->Flink) {
|
||
|
||
PRDBSS_DEVICE_OBJECT RxDeviceObject = CONTAINING_RECORD( ListEntry, RDBSS_DEVICE_OBJECT, MiniRdrListLinks );
|
||
MRxTransportUpdateHandler = RxDeviceObject->Dispatch->MRxTransportUpdateHandler;
|
||
|
||
if ( MRxTransportUpdateHandler != NULL) {
|
||
Status = MRxTransportUpdateHandler(
|
||
pContext->pTransport,
|
||
pContext->TransportEvent,
|
||
pContext->pTransport->pProviderInfo);
|
||
}
|
||
}
|
||
|
||
// Derefrence the transport entry
|
||
RxCeDereferenceTransport(pContext->pTransport);
|
||
|
||
// free the notification context.
|
||
RxFreePool(pContext);
|
||
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
} else {
|
||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
VOID
|
||
MiniRedirectorsNotifier(
|
||
PVOID NotificationContext)
|
||
{
|
||
NTSTATUS Status;
|
||
KIRQL SavedIrql;
|
||
|
||
PLIST_ENTRY pEntry;
|
||
|
||
PRXCE_MINIRDR_NOTIFICATION_CONTEXT pContext;
|
||
PMRX_TRANSPORT_UPDATE_HANDLER MRxTransportUpdateHandler;
|
||
|
||
for (;;) {
|
||
PLIST_ENTRY ListEntry;
|
||
|
||
// Acquire the spin lock ...
|
||
KeAcquireSpinLock(
|
||
&s_RxCeMinirdrNotificationHandler.Lock,
|
||
&SavedIrql);
|
||
|
||
// Remove an item from the notification list.
|
||
if (!IsListEmpty(&s_RxCeMinirdrNotificationHandler.ListHead)) {
|
||
pEntry = RemoveHeadList(
|
||
&s_RxCeMinirdrNotificationHandler.ListHead);
|
||
} else {
|
||
pEntry = NULL;
|
||
s_RxCeMinirdrNotificationHandler.NotifierActive = FALSE;
|
||
}
|
||
|
||
// Release the spin lock
|
||
KeReleaseSpinLock(&s_RxCeMinirdrNotificationHandler.Lock,SavedIrql);
|
||
|
||
if (pEntry == NULL) {
|
||
break;
|
||
}
|
||
|
||
pContext = (PRXCE_MINIRDR_NOTIFICATION_CONTEXT)
|
||
CONTAINING_RECORD(
|
||
pEntry,
|
||
RXCE_MINIRDR_NOTIFICATION_CONTEXT,
|
||
NotificationListEntry);
|
||
|
||
// Notify all the mini redirectors ....
|
||
for (ListEntry = RxRegisteredMiniRdrs.Flink;
|
||
ListEntry!= &RxRegisteredMiniRdrs;
|
||
ListEntry = ListEntry->Flink) {
|
||
|
||
PRDBSS_DEVICE_OBJECT RxDeviceObject = CONTAINING_RECORD( ListEntry, RDBSS_DEVICE_OBJECT, MiniRdrListLinks );
|
||
MRxTransportUpdateHandler = RxDeviceObject->Dispatch->MRxTransportUpdateHandler;
|
||
|
||
if ( MRxTransportUpdateHandler != NULL) {
|
||
Status = MRxTransportUpdateHandler(
|
||
pContext->pTransport,
|
||
pContext->TransportEvent,
|
||
pContext->pTransport->pProviderInfo);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
}
|
||
}
|
||
}
|
||
|
||
// Derefrence the transport entry
|
||
RxCeDereferenceTransport(pContext->pTransport);
|
||
|
||
// free the notification context.
|
||
RxFreePool(pContext);
|
||
}
|
||
}
|
||
|