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);
|
|||
|
}
|
|||
|
}
|
|||
|
|