summaryrefslogtreecommitdiffstats
path: root/private/ntos/se/rmlogon.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/se/rmlogon.c')
-rw-r--r--private/ntos/se/rmlogon.c1137
1 files changed, 1137 insertions, 0 deletions
diff --git a/private/ntos/se/rmlogon.c b/private/ntos/se/rmlogon.c
new file mode 100644
index 000000000..2a1c7a8c6
--- /dev/null
+++ b/private/ntos/se/rmlogon.c
@@ -0,0 +1,1137 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ rmlogon.c
+
+Abstract:
+
+ This module implements the kernel mode logon tracking performed by the
+ reference monitor. Logon tracking is performed by keeping a count of
+ how many tokens exist for each active logon in a system. When a logon
+ session's reference count drops to zero, the LSA is notified so that
+ authentication packages can clean up any related context data.
+
+
+Author:
+
+ Jim Kelly (JimK) 21-April-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+//#define SEP_TRACK_LOGON_SESSION_REFS
+
+
+#include "rmp.h"
+#include <bugcodes.h>
+
+
+SEP_LOGON_SESSION_TERMINATED_NOTIFICATION
+SeFileSystemNotifyRoutinesHead = {0};
+
+
+////////////////////////////////////////////////////////////////////////////
+// //
+// Internally defined data types //
+// //
+////////////////////////////////////////////////////////////////////////////
+
+typedef struct _SEP_FILE_SYSTEM_NOTIFY_CONTEXT {
+ WORK_QUEUE_ITEM WorkItem;
+ LUID LogonId;
+} SEP_FILE_SYSTEM_NOTIFY_CONTEXT, *PSEP_FILE_SYSTEM_NOTIFY_CONTEXT;
+
+
+////////////////////////////////////////////////////////////////////////////
+// //
+// Internally defined routines //
+// //
+////////////////////////////////////////////////////////////////////////////
+
+NTSTATUS
+SepGetLogonSessionTrack(
+ IN PLUID LogonId
+ );
+
+
+VOID
+SepInformLsaOfDeletedLogon(
+ IN PLUID LogonId
+ );
+
+VOID
+SepInformFileSystemsOfDeletedLogon(
+ IN PLUID LogonId
+ );
+
+VOID
+SepNotifyFileSystems(
+ IN PVOID Context
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,SeRegisterLogonSessionTerminatedRoutine)
+#pragma alloc_text(PAGE,SeUnregisterLogonSessionTerminatedRoutine)
+#pragma alloc_text(PAGE,SeMarkLogonSessionForTerminationNotification)
+#pragma alloc_text(PAGE,SepRmCreateLogonSessionWrkr)
+#pragma alloc_text(PAGE,SepRmDeleteLogonSessionWrkr)
+#pragma alloc_text(PAGE,SepReferenceLogonSession)
+#pragma alloc_text(PAGE,SepDeReferenceLogonSession)
+#pragma alloc_text(PAGE,SepCreateLogonSessionTrack)
+#pragma alloc_text(PAGE,SepDeleteLogonSessionTrack)
+#pragma alloc_text(PAGE,SepInformLsaOfDeletedLogon)
+#pragma alloc_text(PAGE,SepInformFileSystemsOfDeletedLogon)
+#pragma alloc_text(PAGE,SepNotifyFileSystems)
+#endif
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// //
+// Local macros //
+// //
+////////////////////////////////////////////////////////////////////////////
+
+
+//
+// This macro is used to obtain an index into the logon session tracking
+// array given a logon session ID (a LUID).
+//
+
+#define SepLogonSessionIndex( PLogonId ) ( \
+ (PLogonId)->LowPart & SEP_LOGON_TRACK_INDEX_MASK \
+ )
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// //
+// Exported Services //
+// //
+////////////////////////////////////////////////////////////////////////////
+
+VOID
+SepRmCreateLogonSessionWrkr(
+ IN PRM_COMMAND_MESSAGE CommandMessage,
+ OUT PRM_REPLY_MESSAGE ReplyMessage
+ )
+
+/*++
+
+Routine Description:
+
+ This function is the dispatch routine for the LSA --> RM
+ "CreateLogonSession" call.
+
+ The arguments passed to this routine are defined by the
+ type SEP_RM_COMMAND_WORKER.
+
+
+Arguments:
+
+ CommandMessage - Points to structure containing RM command message
+ information consisting of an LPC PORT_MESSAGE structure followed
+ by the command number (RmComponentTestCommand) and a command-specific
+ body. The command-specific body of this parameter is a LUID of the
+ logon session to be created.
+
+ ReplyMessage - Pointer to structure containing LSA reply message
+ information consisting of an LPC PORT_MESSAGE structure followed
+ by the command ReturnedStatus field in which a status code from the
+ command will be returned.
+
+Return Value:
+
+ VOID
+
+--*/
+
+{
+
+ NTSTATUS Status;
+ LUID LogonId;
+
+ PAGED_CODE();
+
+ //
+ // Check that command is expected type
+ //
+
+ ASSERT( CommandMessage->CommandNumber == RmCreateLogonSession );
+
+
+ //
+ // Typecast the command parameter to what we expect.
+ //
+
+ LogonId = *((LUID UNALIGNED *) CommandMessage->CommandParams);
+
+
+
+ //
+ // Try to create the logon session tracking record
+ //
+
+ Status = SepCreateLogonSessionTrack( &LogonId );
+
+
+
+ //
+ // Set the reply status
+ //
+
+ ReplyMessage->ReturnedStatus = Status;
+
+
+ return;
+}
+
+
+
+VOID
+SepRmDeleteLogonSessionWrkr(
+ IN PRM_COMMAND_MESSAGE CommandMessage,
+ OUT PRM_REPLY_MESSAGE ReplyMessage
+ )
+
+/*++
+
+Routine Description:
+
+ This function is the dispatch routine for the LSA --> RM
+ "DeleteLogonSession" call.
+
+ The arguments passed to this routine are defined by the
+ type SEP_RM_COMMAND_WORKER.
+
+
+Arguments:
+
+ CommandMessage - Points to structure containing RM command message
+ information consisting of an LPC PORT_MESSAGE structure followed
+ by the command number (RmComponentTestCommand) and a command-specific
+ body. The command-specific body of this parameter is a LUID of the
+ logon session to be created.
+
+ ReplyMessage - Pointer to structure containing LSA reply message
+ information consisting of an LPC PORT_MESSAGE structure followed
+ by the command ReturnedStatus field in which a status code from the
+ command will be returned.
+
+Return Value:
+
+ VOID
+
+--*/
+
+{
+
+ NTSTATUS Status;
+ LUID LogonId;
+
+ PAGED_CODE();
+
+ //
+ // Check that command is expected type
+ //
+
+ ASSERT( CommandMessage->CommandNumber == RmDeleteLogonSession );
+
+
+ //
+ // Typecast the command parameter to what we expect.
+ //
+
+ LogonId = *((LUID UNALIGNED *) CommandMessage->CommandParams);
+
+
+
+ //
+ // Try to create the logon session tracking record
+ //
+
+ Status = SepDeleteLogonSessionTrack( &LogonId );
+
+
+
+ //
+ // Set the reply status
+ //
+
+ ReplyMessage->ReturnedStatus = Status;
+
+
+ return;
+}
+
+
+
+NTSTATUS
+SepReferenceLogonSession(
+ IN PLUID LogonId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine increments the reference count of a logon session
+ tracking record.
+
+
+
+Arguments:
+
+ LogonId - Pointer to the logon session ID whose logon track is
+ to be incremented.
+
+Return Value:
+
+ STATUS_SUCCESS - The reference count was successfully incremented.
+
+ STATUS_NO_SUCH_LOGON_SESSION - The specified logon session doesn't
+ exist in the reference monitor's database.
+
+--*/
+
+{
+
+ ULONG SessionArrayIndex;
+ PSEP_LOGON_SESSION_REFERENCES Previous, Current;
+
+#ifdef SEP_TRACK_LOGON_SESSION_REFS
+ ULONG Refs;
+#endif //SEP_TRACK_LOGON_SESSION_REFS
+
+ PAGED_CODE();
+
+ SessionArrayIndex = SepLogonSessionIndex( LogonId );
+
+ //
+ // Protect modification of reference monitor database
+ //
+
+ SepRmAcquireDbWriteLock();
+
+
+ //
+ // Now walk the list for our logon session array hash index.
+ //
+
+ Previous = (PSEP_LOGON_SESSION_REFERENCES)
+ ((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
+ Current = Previous->Next;
+
+ while (Current != NULL) {
+
+ //
+ // If we found it, increment the reference count and return
+ //
+
+ if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
+#ifdef SEP_TRACK_LOGON_SESSION_REFS
+ ULONG Refs;
+#endif //SEP_TRACK_LOGON_SESSION_REFS
+
+ Current->ReferenceCount += 1;
+
+#ifdef SEP_TRACK_LOGON_SESSION_REFS
+ Refs = Current->ReferenceCount;
+#endif //SEP_TRACK_LOGON_SESSION_REFS
+
+ SepRmReleaseDbWriteLock();
+
+#ifdef SEP_TRACK_LOGON_SESSION_REFS
+ DbgPrint("SE (rm): ++ logon session: (%d, %d) to %d by (%d, %d)\n",
+ LogonId->HighPart, LogonId->LowPart, Refs,
+ PsGetCurrentThread()->Cid.UniqueProcess,
+ PsGetCurrentThread()->Cid.UniqueThread);
+
+#endif //SEP_TRACK_LOGON_SESSION_REFS
+ return STATUS_SUCCESS;
+ }
+
+ Previous = Current;
+ Current = Current->Next;
+ }
+
+ SepRmReleaseDbWriteLock();
+
+ //
+ // Bad news, someone asked us to increment the reference count of
+ // a logon session we didn't know existed. This might be a new
+ // token being created, so return an error status and let the caller
+ // decide if it warrants a bug check or not.
+ //
+
+
+ return STATUS_NO_SUCH_LOGON_SESSION;
+
+
+
+}
+
+
+VOID
+SepDeReferenceLogonSession(
+ IN PLUID LogonId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine decrements the reference count of a logon session
+ tracking record.
+
+ If the reference count is decremented to zero, then there is no
+ possibility for any more tokens to exist for the logon session.
+ In this case, the LSA is notified that a logon session has
+ terminated.
+
+
+
+Arguments:
+
+ LogonId - Pointer to the logon session ID whose logon track is
+ to be decremented.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG SessionArrayIndex;
+ PSEP_LOGON_SESSION_REFERENCES Previous, Current;
+
+#ifdef SEP_TRACK_LOGON_SESSION_REFS
+ ULONG Refs;
+#endif //SEP_TRACK_LOGON_SESSION_REFS
+
+ PAGED_CODE();
+
+ SessionArrayIndex = SepLogonSessionIndex( LogonId );
+
+ //
+ // Protect modification of reference monitor database
+ //
+
+ SepRmAcquireDbWriteLock();
+
+
+ //
+ // Now walk the list for our logon session array hash index.
+ //
+
+ Previous = (PSEP_LOGON_SESSION_REFERENCES)
+ ((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
+ Current = Previous->Next;
+
+ while (Current != NULL) {
+
+ //
+ // If we found it, decrement the reference count and return
+ //
+
+ if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
+ Current->ReferenceCount -= 1;
+ if (Current->ReferenceCount == 0) {
+
+ //
+ // Pull it from the list
+ //
+
+ Previous->Next = Current->Next;
+
+
+ //
+ // No longer need to protect our pointer to this
+ // record.
+ //
+
+ SepRmReleaseDbWriteLock();
+
+ //
+ // Asynchronoously inform file systems that this logon session
+ // is going away, if atleast one FS expressed interest in this
+ // logon session.
+ //
+
+ if (Current->Flags & SEP_TERMINATION_NOTIFY) {
+ SepInformFileSystemsOfDeletedLogon( LogonId );
+ }
+
+ //
+ // Deallocate the logon session track record.
+ //
+
+ ExFreePool( (PVOID)Current );
+
+
+#ifdef SEP_TRACK_LOGON_SESSION_REFS
+ DbgPrint("SE (rm): -- ** logon session: (%d, %d) to ZERO by (%d, %d)\n",
+ LogonId->HighPart, LogonId->LowPart,
+ PsGetCurrentThread()->Cid.UniqueProcess,
+ PsGetCurrentThread()->Cid.UniqueThread);
+
+#endif //SEP_TRACK_LOGON_SESSION_REFS
+
+ //
+ // Inform the LSA about the deletion of this logon session.
+ //
+
+ SepInformLsaOfDeletedLogon( LogonId );
+
+
+
+ return;
+
+ }
+
+ //
+ // reference count was incremented, but not to zero.
+ //
+
+#ifdef SEP_TRACK_LOGON_SESSION_REFS
+ Refs = Current->ReferenceCount;
+#endif //SEP_TRACK_LOGON_SESSION_REFS
+
+ SepRmReleaseDbWriteLock();
+
+#ifdef SEP_TRACK_LOGON_SESSION_REFS
+ DbgPrint("SE (rm): -- logon session: (%d, %d) to %d by (%d, %d)\n",
+ LogonId->HighPart, LogonId->LowPart, Refs,
+ PsGetCurrentThread()->Cid.UniqueProcess,
+ PsGetCurrentThread()->Cid.UniqueThread);
+#endif //SEP_TRACK_LOGON_SESSION_REFS
+
+ return;
+ }
+
+ Previous = Current;
+ Current = Current->Next;
+ }
+
+ SepRmReleaseDbWriteLock();
+
+ //
+ // Bad news, someone asked us to decrement the reference count of
+ // a logon session we didn't know existed.
+ //
+
+ KeBugCheck( DEREF_UNKNOWN_LOGON_SESSION );
+
+ return;
+
+}
+
+
+NTSTATUS
+SepCreateLogonSessionTrack(
+ IN PLUID LogonId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine creates a new logon session tracking record.
+
+ This should only be called as a dispatch routine for a LSA->RM
+ call (and once during system initialization).
+
+ If the specified logon session already exists, then an error is returned.
+
+
+
+Arguments:
+
+ LogonId - Pointer to the logon session ID for which a new logon track is
+ to be created.
+
+Return Value:
+
+ STATUS_SUCCESS - The logon session track was created successfully.
+
+ STATUS_LOGON_SESSION_EXISTS - The logon session already exists.
+ A new one has not been created.
+
+--*/
+
+{
+
+ ULONG SessionArrayIndex;
+ PSEP_LOGON_SESSION_REFERENCES Previous, Current;
+ PSEP_LOGON_SESSION_REFERENCES LogonSessionTrack;
+
+ PAGED_CODE();
+
+ //
+ // Make sure we can allocate a new logon session track record
+ //
+
+ LogonSessionTrack = (PSEP_LOGON_SESSION_REFERENCES)
+ ExAllocatePoolWithTag(
+ PagedPool,
+ sizeof(SEP_LOGON_SESSION_REFERENCES),
+ 'sLeS'
+ );
+
+ if (LogonSessionTrack == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ LogonSessionTrack->LogonId = (*LogonId);
+ LogonSessionTrack->ReferenceCount = 0;
+
+
+
+ SessionArrayIndex = SepLogonSessionIndex( LogonId );
+
+ //
+ // Protect modification of reference monitor database
+ //
+
+ SepRmAcquireDbWriteLock();
+
+
+ //
+ // Now walk the list for our logon session array hash index
+ // looking for a duplicate logon session ID.
+ //
+
+ Previous = (PSEP_LOGON_SESSION_REFERENCES)
+ ((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
+ Current = Previous->Next;
+
+ while (Current != NULL) {
+
+ if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
+
+ //
+ // One already exists. Hmmm.
+ //
+
+ SepRmReleaseDbWriteLock();
+ ExFreePool(LogonSessionTrack);
+ return STATUS_LOGON_SESSION_EXISTS;
+
+ }
+
+ Previous = Current;
+ Current = Current->Next;
+ }
+
+
+ //
+ // Reached the end of the list without finding a duplicate.
+ // Add the new one.
+ //
+
+ LogonSessionTrack->Next = SepLogonSessions[ SessionArrayIndex ];
+ SepLogonSessions[ SessionArrayIndex ] = LogonSessionTrack;
+
+
+
+
+ SepRmReleaseDbWriteLock();
+ return STATUS_SUCCESS;
+
+}
+
+
+NTSTATUS
+SepDeleteLogonSessionTrack(
+ IN PLUID LogonId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine creates a new logon session tracking record.
+
+ This should only be called as a dispatch routine for a LSA->RM
+ call (and once during system initialization).
+
+ If the specified logon session already exists, then an error is returned.
+
+
+
+Arguments:
+
+ LogonId - Pointer to the logon session ID whose logon track is
+ to be deleted.
+
+Return Value:
+
+ STATUS_SUCCESS - The logon session track was deleted successfully.
+
+ STATUS_BAD_LOGON_SESSION_STATE - The logon session has a non-zero
+ reference count and can not be deleted.
+
+ STATUS_NO_SUCH_LOGON_SESSION - The specified logon session does not
+ exist.
+
+
+--*/
+
+{
+
+ ULONG SessionArrayIndex;
+ PSEP_LOGON_SESSION_REFERENCES Previous, Current;
+
+ PAGED_CODE();
+
+ SessionArrayIndex = SepLogonSessionIndex( LogonId );
+
+ //
+ // Protect modification of reference monitor database
+ //
+
+ SepRmAcquireDbWriteLock();
+
+
+ //
+ // Now walk the list for our logon session array hash index.
+ //
+
+ Previous = (PSEP_LOGON_SESSION_REFERENCES)
+ ((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
+ Current = Previous->Next;
+
+ while (Current != NULL) {
+
+ //
+ // If we found it, make sure reference count is zero
+ //
+
+ if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
+
+ if (Current->ReferenceCount == 0) {
+
+ //
+ // Pull it from the list
+ //
+
+ Previous->Next = Current->Next;
+
+
+ //
+ // No longer need to protect our pointer to this
+ // record.
+ //
+
+ SepRmReleaseDbWriteLock();
+
+
+ //
+ // Deallocate the logon session track record.
+ //
+
+ ExFreePool( (PVOID)Current );
+
+
+ return STATUS_SUCCESS;
+
+ }
+
+ //
+ // reference count was not zero. This is not considered
+ // a healthy situation. Return an error and let someone
+ // else declare the bug check.
+ //
+
+ SepRmReleaseDbWriteLock();
+ return STATUS_BAD_LOGON_SESSION_STATE;
+ }
+
+ Previous = Current;
+ Current = Current->Next;
+ }
+
+ SepRmReleaseDbWriteLock();
+
+ //
+ // Someone asked us to delete a logon session that isn't
+ // in the database.
+ //
+
+ return STATUS_NO_SUCH_LOGON_SESSION;
+
+}
+
+
+VOID
+SepInformLsaOfDeletedLogon(
+ IN PLUID LogonId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine informs the LSA about the deletion of a logon session.
+
+ Note that we can not be guaranteed that we are in a whole (or wholesome)
+ thread, since we may be in the middle of process deletion and object
+ rundown. Therefore, we must queue the work off to a worker thread which
+ can then make an LPC call to the LSA.
+
+
+
+
+Arguments:
+
+ LogonId - Pointer to the logon session ID which has been deleted.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PSEP_LSA_WORK_ITEM DeleteLogonItem;
+
+ PAGED_CODE();
+
+ //
+ // Pass the LUID value along with the work queue item.
+ // Note that the worker thread is responsible for freeing the WorkItem data
+ // structure.
+ //
+
+ DeleteLogonItem = ExAllocatePoolWithTag( PagedPool, sizeof(SEP_LSA_WORK_ITEM), 'wLeS' );
+ if (DeleteLogonItem == NULL) {
+
+ //
+ // I don't know what to do here... we loose track of a logon session,
+ // but the system isn't really harmed in any way.
+ //
+
+ return;
+
+ }
+
+ DeleteLogonItem->CommandParams.LogonId = (*LogonId);
+ DeleteLogonItem->CommandNumber = LsapLogonSessionDeletedCommand;
+ DeleteLogonItem->CommandParamsLength = sizeof( LUID );
+ DeleteLogonItem->ReplyBuffer = NULL;
+ DeleteLogonItem->ReplyBufferLength = 0;
+ DeleteLogonItem->CleanupFunction = NULL;
+ DeleteLogonItem->CleanupParameter = 0;
+ DeleteLogonItem->Tag = SepDeleteLogon;
+ DeleteLogonItem->CommandParamsMemoryType = SepRmImmediateMemory;
+
+ if (!SepQueueWorkItem( DeleteLogonItem, TRUE )) {
+
+ ExFreePool( DeleteLogonItem );
+ }
+
+ return;
+
+}
+
+
+NTSTATUS
+SeRegisterLogonSessionTerminatedRoutine(
+ IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called by file systems that are interested in being
+ notified when a logon session is being deleted.
+
+Arguments:
+
+ CallbackRoutine - Address of routine to call back when a logon session
+ is being deleted.
+
+Return Value:
+
+ STATUS_SUCCESS - Successfully registered routine
+
+ STATUS_INVALID_PARAMETER - CallbackRoutine is NULL
+
+ STATUS_INSUFFICIENT_RESOURCE - Unable to allocate list entry.
+
+--*/
+
+{
+ PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION NewCallback;
+
+ PAGED_CODE();
+
+ if (CallbackRoutine == NULL) {
+ return( STATUS_INVALID_PARAMETER );
+ }
+
+ NewCallback = ExAllocatePoolWithTag(
+ PagedPool,
+ sizeof(SEP_LOGON_SESSION_TERMINATED_NOTIFICATION),
+ 'SFeS');
+
+ if (NewCallback == NULL) {
+ return( STATUS_INSUFFICIENT_RESOURCES );
+ }
+
+ SepRmAcquireDbWriteLock();
+
+ NewCallback->Next = SeFileSystemNotifyRoutinesHead.Next;
+
+ NewCallback->CallbackRoutine = CallbackRoutine;
+
+ SeFileSystemNotifyRoutinesHead.Next = NewCallback;
+
+ SepRmReleaseDbWriteLock();
+
+ return( STATUS_SUCCESS );
+}
+
+
+NTSTATUS
+SeUnregisterLogonSessionTerminatedRoutine(
+ IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine
+ )
+
+/*++
+
+Routine Description:
+
+ This is the dual of SeRegisterLogonSessionTerminatedRoutine. A File System
+ *MUST* call this before it is unloaded.
+
+Arguments:
+
+ CallbackRoutine - Address of routine that was originally passed in to
+ SeRegisterLogonSessionTerminatedRoutine.
+
+Return Value:
+
+ STATUS_SUCCESS - Successfully removed callback routine
+
+ STATUS_INVALID_PARAMETER - CallbackRoutine is NULL
+
+ STATUS_NOT_FOUND - Didn't find and entry for CallbackRoutine
+
+--*/
+{
+ NTSTATUS Status;
+ PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION PreviousEntry;
+ PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION NotifyEntry;
+
+ PAGED_CODE();
+
+ if (CallbackRoutine == NULL) {
+ return( STATUS_INVALID_PARAMETER );
+ }
+
+ SepRmAcquireDbWriteLock();
+
+ for (PreviousEntry = &SeFileSystemNotifyRoutinesHead,
+ NotifyEntry = SeFileSystemNotifyRoutinesHead.Next;
+ NotifyEntry != NULL;
+ PreviousEntry = NotifyEntry,
+ NotifyEntry = NotifyEntry->Next) {
+
+ if (NotifyEntry->CallbackRoutine == CallbackRoutine)
+ break;
+
+ }
+
+ if (NotifyEntry != NULL) {
+
+ PreviousEntry->Next = NotifyEntry->Next;
+
+ ExFreePool( NotifyEntry );
+
+ Status = STATUS_SUCCESS;
+
+ } else {
+
+ Status = STATUS_NOT_FOUND;
+
+ }
+
+ SepRmReleaseDbWriteLock();
+
+ return( Status );
+
+}
+
+
+NTSTATUS
+SeMarkLogonSessionForTerminationNotification(
+ IN PLUID LogonId
+ )
+
+/*++
+
+Routine Description:
+
+ File systems that have registered for logon-termination notification
+ can mark logon sessions they are interested in for callback by calling
+ this routine.
+
+Arguments:
+
+ LogonId - The logon id for which the file system should be notified
+ when the logon session is terminated.
+
+Returns:
+
+ Nothing.
+
+--*/
+
+{
+
+ ULONG SessionArrayIndex;
+ PSEP_LOGON_SESSION_REFERENCES Previous, Current;
+
+ PAGED_CODE();
+
+ SessionArrayIndex = SepLogonSessionIndex( LogonId );
+
+ //
+ // Protect modification of reference monitor database
+ //
+
+ SepRmAcquireDbWriteLock();
+
+
+ //
+ // Now walk the list for our logon session array hash index.
+ //
+
+ Previous = (PSEP_LOGON_SESSION_REFERENCES)
+ ((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
+ Current = Previous->Next;
+
+ while (Current != NULL) {
+
+ //
+ // If we found it, decrement the reference count and return
+ //
+
+ if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
+ Current->Flags |= SEP_TERMINATION_NOTIFY;
+ break;
+ }
+
+ Previous = Current;
+ Current = Current->Next;
+ }
+
+ SepRmReleaseDbWriteLock();
+
+ return( (Current != NULL) ? STATUS_SUCCESS : STATUS_NOT_FOUND );
+
+}
+
+
+VOID
+SepInformFileSystemsOfDeletedLogon(
+ IN PLUID LogonId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine informs interested file systems of a deleted logon.
+
+ Note that we can not be guaranteed that we are in a whole (or wholesome)
+ thread, since we may be in the middle of process deletion and object
+ rundown. Therefore, we must queue the work off to a worker thread.
+
+
+Arguments:
+
+ LogonId - Pointer to the logon session ID which has been deleted.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PSEP_FILE_SYSTEM_NOTIFY_CONTEXT FSNotifyContext;
+
+ PAGED_CODE();
+
+ FSNotifyContext = ExAllocatePoolWithTag(
+ NonPagedPool,
+ sizeof(SEP_FILE_SYSTEM_NOTIFY_CONTEXT),
+ 'SFeS');
+
+ if (FSNotifyContext == NULL) {
+
+ //
+ // I don't know what to do here... file systems will loose track of a
+ // logon session, but the system isn't really harmed in any way.
+ //
+
+ return;
+
+ }
+
+ FSNotifyContext->LogonId = *LogonId;
+
+ ExInitializeWorkItem( &FSNotifyContext->WorkItem,
+ (PWORKER_THREAD_ROUTINE) SepNotifyFileSystems,
+ (PVOID) FSNotifyContext);
+
+ ExQueueWorkItem( &FSNotifyContext->WorkItem, DelayedWorkQueue );
+
+}
+
+
+VOID
+SepNotifyFileSystems(
+ IN PVOID Context
+ )
+{
+ PSEP_FILE_SYSTEM_NOTIFY_CONTEXT FSNotifyContext =
+ (PSEP_FILE_SYSTEM_NOTIFY_CONTEXT) Context;
+
+ PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION NextCallback;
+
+ PAGED_CODE();
+
+ //
+ // Protect modification of the list of FS callbacks.
+ //
+
+ SepRmAcquireDbReadLock();
+
+ NextCallback = SeFileSystemNotifyRoutinesHead.Next;
+
+ while (NextCallback != NULL) {
+
+ NextCallback->CallbackRoutine( &FSNotifyContext->LogonId );
+
+ NextCallback = NextCallback->Next;
+ }
+
+ SepRmReleaseDbReadLock();
+
+ ExFreePool( FSNotifyContext );
+}
+