windows-nt/Source/XPSP1/NT/base/fs/rdr2/rxce/daytona/rxcep.c

224 lines
6.9 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
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);
}
}