Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

rmlogon.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 rmlogon.c 00008 00009 Abstract: 00010 00011 This module implements the kernel mode logon tracking performed by the 00012 reference monitor. Logon tracking is performed by keeping a count of 00013 how many tokens exist for each active logon in a system. When a logon 00014 session's reference count drops to zero, the LSA is notified so that 00015 authentication packages can clean up any related context data. 00016 00017 00018 Author: 00019 00020 Jim Kelly (JimK) 21-April-1991 00021 00022 Environment: 00023 00024 Kernel mode only. 00025 00026 Revision History: 00027 00028 --*/ 00029 00030 //#define SEP_TRACK_LOGON_SESSION_REFS 00031 00032 00033 #include "rmp.h" 00034 #include <bugcodes.h> 00035 00036 00037 SEP_LOGON_SESSION_TERMINATED_NOTIFICATION 00038 SeFileSystemNotifyRoutinesHead = {0}; 00039 00040 00042 // // 00043 // Internally defined data types // 00044 // // 00046 00047 typedef struct _SEP_FILE_SYSTEM_NOTIFY_CONTEXT { 00048 WORK_QUEUE_ITEM WorkItem; 00049 LUID LogonId; 00050 } SEP_FILE_SYSTEM_NOTIFY_CONTEXT, *PSEP_FILE_SYSTEM_NOTIFY_CONTEXT; 00051 00052 00054 // // 00055 // Internally defined routines // 00056 // // 00058 00059 NTSTATUS 00060 SepGetLogonSessionTrack( 00061 IN PLUID LogonId 00062 ); 00063 00064 00065 VOID 00066 SepInformLsaOfDeletedLogon( 00067 IN PLUID LogonId 00068 ); 00069 00070 VOID 00071 SepInformFileSystemsOfDeletedLogon( 00072 IN PLUID LogonId 00073 ); 00074 00075 VOID 00076 SepNotifyFileSystems( 00077 IN PVOID Context 00078 ); 00079 00080 #ifdef ALLOC_PRAGMA 00081 #pragma alloc_text(PAGE,SeRegisterLogonSessionTerminatedRoutine) 00082 #pragma alloc_text(PAGE,SeUnregisterLogonSessionTerminatedRoutine) 00083 #pragma alloc_text(PAGE,SeMarkLogonSessionForTerminationNotification) 00084 #pragma alloc_text(PAGE,SepRmCreateLogonSessionWrkr) 00085 #pragma alloc_text(PAGE,SepRmDeleteLogonSessionWrkr) 00086 #pragma alloc_text(PAGE,SepReferenceLogonSession) 00087 #pragma alloc_text(PAGE,SepDeReferenceLogonSession) 00088 #pragma alloc_text(PAGE,SepCreateLogonSessionTrack) 00089 #pragma alloc_text(PAGE,SepDeleteLogonSessionTrack) 00090 #pragma alloc_text(PAGE,SepInformLsaOfDeletedLogon) 00091 #pragma alloc_text(PAGE,SepInformFileSystemsOfDeletedLogon) 00092 #pragma alloc_text(PAGE,SepNotifyFileSystems) 00093 #endif 00094 00095 00096 00098 // // 00099 // Local macros // 00100 // // 00102 00103 00104 // 00105 // This macro is used to obtain an index into the logon session tracking 00106 // array given a logon session ID (a LUID). 00107 // 00108 00109 #define SepLogonSessionIndex( PLogonId ) ( \ 00110 (PLogonId)->LowPart & SEP_LOGON_TRACK_INDEX_MASK \ 00111 ) 00112 00113 00114 00116 // // 00117 // Exported Services // 00118 // // 00120 00121 VOID 00122 SepRmCreateLogonSessionWrkr( 00123 IN PRM_COMMAND_MESSAGE CommandMessage, 00124 OUT PRM_REPLY_MESSAGE ReplyMessage 00125 ) 00126 00127 /*++ 00128 00129 Routine Description: 00130 00131 This function is the dispatch routine for the LSA --> RM 00132 "CreateLogonSession" call. 00133 00134 The arguments passed to this routine are defined by the 00135 type SEP_RM_COMMAND_WORKER. 00136 00137 00138 Arguments: 00139 00140 CommandMessage - Points to structure containing RM command message 00141 information consisting of an LPC PORT_MESSAGE structure followed 00142 by the command number (RmComponentTestCommand) and a command-specific 00143 body. The command-specific body of this parameter is a LUID of the 00144 logon session to be created. 00145 00146 ReplyMessage - Pointer to structure containing LSA reply message 00147 information consisting of an LPC PORT_MESSAGE structure followed 00148 by the command ReturnedStatus field in which a status code from the 00149 command will be returned. 00150 00151 Return Value: 00152 00153 VOID 00154 00155 --*/ 00156 00157 { 00158 00159 NTSTATUS Status; 00160 LUID LogonId; 00161 00162 PAGED_CODE(); 00163 00164 // 00165 // Check that command is expected type 00166 // 00167 00168 ASSERT( CommandMessage->CommandNumber == RmCreateLogonSession ); 00169 00170 00171 // 00172 // Typecast the command parameter to what we expect. 00173 // 00174 00175 LogonId = *((LUID UNALIGNED *) CommandMessage->CommandParams); 00176 00177 00178 00179 // 00180 // Try to create the logon session tracking record 00181 // 00182 00183 Status = SepCreateLogonSessionTrack( &LogonId ); 00184 00185 00186 00187 // 00188 // Set the reply status 00189 // 00190 00191 ReplyMessage->ReturnedStatus = Status; 00192 00193 00194 return; 00195 } 00196 00197 00198 00199 VOID 00200 SepRmDeleteLogonSessionWrkr( 00201 IN PRM_COMMAND_MESSAGE CommandMessage, 00202 OUT PRM_REPLY_MESSAGE ReplyMessage 00203 ) 00204 00205 /*++ 00206 00207 Routine Description: 00208 00209 This function is the dispatch routine for the LSA --> RM 00210 "DeleteLogonSession" call. 00211 00212 The arguments passed to this routine are defined by the 00213 type SEP_RM_COMMAND_WORKER. 00214 00215 00216 Arguments: 00217 00218 CommandMessage - Points to structure containing RM command message 00219 information consisting of an LPC PORT_MESSAGE structure followed 00220 by the command number (RmComponentTestCommand) and a command-specific 00221 body. The command-specific body of this parameter is a LUID of the 00222 logon session to be created. 00223 00224 ReplyMessage - Pointer to structure containing LSA reply message 00225 information consisting of an LPC PORT_MESSAGE structure followed 00226 by the command ReturnedStatus field in which a status code from the 00227 command will be returned. 00228 00229 Return Value: 00230 00231 VOID 00232 00233 --*/ 00234 00235 { 00236 00237 NTSTATUS Status; 00238 LUID LogonId; 00239 00240 PAGED_CODE(); 00241 00242 // 00243 // Check that command is expected type 00244 // 00245 00246 ASSERT( CommandMessage->CommandNumber == RmDeleteLogonSession ); 00247 00248 00249 // 00250 // Typecast the command parameter to what we expect. 00251 // 00252 00253 LogonId = *((LUID UNALIGNED *) CommandMessage->CommandParams); 00254 00255 00256 00257 // 00258 // Try to create the logon session tracking record 00259 // 00260 00261 Status = SepDeleteLogonSessionTrack( &LogonId ); 00262 00263 00264 00265 // 00266 // Set the reply status 00267 // 00268 00269 ReplyMessage->ReturnedStatus = Status; 00270 00271 00272 return; 00273 } 00274 00275 00276 00277 NTSTATUS 00278 SepReferenceLogonSession( 00279 IN PLUID LogonId 00280 ) 00281 00282 /*++ 00283 00284 Routine Description: 00285 00286 This routine increments the reference count of a logon session 00287 tracking record. 00288 00289 00290 00291 Arguments: 00292 00293 LogonId - Pointer to the logon session ID whose logon track is 00294 to be incremented. 00295 00296 Return Value: 00297 00298 STATUS_SUCCESS - The reference count was successfully incremented. 00299 00300 STATUS_NO_SUCH_LOGON_SESSION - The specified logon session doesn't 00301 exist in the reference monitor's database. 00302 00303 --*/ 00304 00305 { 00306 00307 ULONG SessionArrayIndex; 00308 PSEP_LOGON_SESSION_REFERENCES Previous, Current; 00309 00310 #ifdef SEP_TRACK_LOGON_SESSION_REFS 00311 ULONG Refs; 00312 #endif //SEP_TRACK_LOGON_SESSION_REFS 00313 00314 PAGED_CODE(); 00315 00316 SessionArrayIndex = SepLogonSessionIndex( LogonId ); 00317 00318 // 00319 // Protect modification of reference monitor database 00320 // 00321 00322 SepRmAcquireDbWriteLock(); 00323 00324 00325 // 00326 // Now walk the list for our logon session array hash index. 00327 // 00328 00329 Previous = (PSEP_LOGON_SESSION_REFERENCES) 00330 ((PVOID)&SepLogonSessions[ SessionArrayIndex ]); 00331 Current = Previous->Next; 00332 00333 while (Current != NULL) { 00334 00335 // 00336 // If we found it, increment the reference count and return 00337 // 00338 00339 if (RtlEqualLuid( LogonId, &Current->LogonId) ) { 00340 #ifdef SEP_TRACK_LOGON_SESSION_REFS 00341 ULONG Refs; 00342 #endif //SEP_TRACK_LOGON_SESSION_REFS 00343 00344 Current->ReferenceCount += 1; 00345 00346 #ifdef SEP_TRACK_LOGON_SESSION_REFS 00347 Refs = Current->ReferenceCount; 00348 #endif //SEP_TRACK_LOGON_SESSION_REFS 00349 00350 SepRmReleaseDbWriteLock(); 00351 00352 #ifdef SEP_TRACK_LOGON_SESSION_REFS 00353 DbgPrint("SE (rm): ++ logon session: (%d, %d) to %d by (%d, %d)\n", 00354 LogonId->HighPart, LogonId->LowPart, Refs, 00355 PsGetCurrentThread()->Cid.UniqueProcess, 00356 PsGetCurrentThread()->Cid.UniqueThread); 00357 00358 #endif //SEP_TRACK_LOGON_SESSION_REFS 00359 return STATUS_SUCCESS; 00360 } 00361 00362 Previous = Current; 00363 Current = Current->Next; 00364 } 00365 00366 SepRmReleaseDbWriteLock(); 00367 00368 // 00369 // Bad news, someone asked us to increment the reference count of 00370 // a logon session we didn't know existed. This might be a new 00371 // token being created, so return an error status and let the caller 00372 // decide if it warrants a bug check or not. 00373 // 00374 00375 00376 return STATUS_NO_SUCH_LOGON_SESSION; 00377 00378 00379 00380 } 00381 00382 00383 VOID 00384 SepDeReferenceLogonSession( 00385 IN PLUID LogonId 00386 ) 00387 00388 /*++ 00389 00390 Routine Description: 00391 00392 This routine decrements the reference count of a logon session 00393 tracking record. 00394 00395 If the reference count is decremented to zero, then there is no 00396 possibility for any more tokens to exist for the logon session. 00397 In this case, the LSA is notified that a logon session has 00398 terminated. 00399 00400 00401 00402 Arguments: 00403 00404 LogonId - Pointer to the logon session ID whose logon track is 00405 to be decremented. 00406 00407 Return Value: 00408 00409 None. 00410 00411 --*/ 00412 00413 { 00414 00415 ULONG SessionArrayIndex; 00416 PSEP_LOGON_SESSION_REFERENCES Previous, Current; 00417 00418 #ifdef SEP_TRACK_LOGON_SESSION_REFS 00419 ULONG Refs; 00420 #endif //SEP_TRACK_LOGON_SESSION_REFS 00421 00422 PAGED_CODE(); 00423 00424 SessionArrayIndex = SepLogonSessionIndex( LogonId ); 00425 00426 // 00427 // Protect modification of reference monitor database 00428 // 00429 00430 SepRmAcquireDbWriteLock(); 00431 00432 00433 // 00434 // Now walk the list for our logon session array hash index. 00435 // 00436 00437 Previous = (PSEP_LOGON_SESSION_REFERENCES) 00438 ((PVOID)&SepLogonSessions[ SessionArrayIndex ]); 00439 Current = Previous->Next; 00440 00441 while (Current != NULL) { 00442 00443 // 00444 // If we found it, decrement the reference count and return 00445 // 00446 00447 if (RtlEqualLuid( LogonId, &Current->LogonId) ) { 00448 Current->ReferenceCount -= 1; 00449 if (Current->ReferenceCount == 0) { 00450 00451 // 00452 // Pull it from the list 00453 // 00454 00455 Previous->Next = Current->Next; 00456 00457 00458 // 00459 // No longer need to protect our pointer to this 00460 // record. 00461 // 00462 00463 SepRmReleaseDbWriteLock(); 00464 00465 // 00466 // Asynchronoously inform file systems that this logon session 00467 // is going away, if atleast one FS expressed interest in this 00468 // logon session. 00469 // 00470 00471 if (Current->Flags & SEP_TERMINATION_NOTIFY) { 00472 SepInformFileSystemsOfDeletedLogon( LogonId ); 00473 } 00474 00475 // 00476 // Deallocate the logon session track record. 00477 // 00478 00479 ExFreePool( (PVOID)Current ); 00480 00481 00482 #ifdef SEP_TRACK_LOGON_SESSION_REFS 00483 DbgPrint("SE (rm): -- ** logon session: (%d, %d) to ZERO by (%d, %d)\n", 00484 LogonId->HighPart, LogonId->LowPart, 00485 PsGetCurrentThread()->Cid.UniqueProcess, 00486 PsGetCurrentThread()->Cid.UniqueThread); 00487 00488 #endif //SEP_TRACK_LOGON_SESSION_REFS 00489 00490 // 00491 // Inform the LSA about the deletion of this logon session. 00492 // 00493 00494 SepInformLsaOfDeletedLogon( LogonId ); 00495 00496 00497 00498 return; 00499 00500 } 00501 00502 // 00503 // reference count was incremented, but not to zero. 00504 // 00505 00506 #ifdef SEP_TRACK_LOGON_SESSION_REFS 00507 Refs = Current->ReferenceCount; 00508 #endif //SEP_TRACK_LOGON_SESSION_REFS 00509 00510 SepRmReleaseDbWriteLock(); 00511 00512 #ifdef SEP_TRACK_LOGON_SESSION_REFS 00513 DbgPrint("SE (rm): -- logon session: (%d, %d) to %d by (%d, %d)\n", 00514 LogonId->HighPart, LogonId->LowPart, Refs, 00515 PsGetCurrentThread()->Cid.UniqueProcess, 00516 PsGetCurrentThread()->Cid.UniqueThread); 00517 #endif //SEP_TRACK_LOGON_SESSION_REFS 00518 00519 return; 00520 } 00521 00522 Previous = Current; 00523 Current = Current->Next; 00524 } 00525 00526 SepRmReleaseDbWriteLock(); 00527 00528 // 00529 // Bad news, someone asked us to decrement the reference count of 00530 // a logon session we didn't know existed. 00531 // 00532 00533 KeBugCheck( DEREF_UNKNOWN_LOGON_SESSION ); 00534 00535 return; 00536 00537 } 00538 00539 00540 NTSTATUS 00541 SepCreateLogonSessionTrack( 00542 IN PLUID LogonId 00543 ) 00544 00545 /*++ 00546 00547 Routine Description: 00548 00549 This routine creates a new logon session tracking record. 00550 00551 This should only be called as a dispatch routine for a LSA->RM 00552 call (and once during system initialization). 00553 00554 If the specified logon session already exists, then an error is returned. 00555 00556 00557 00558 Arguments: 00559 00560 LogonId - Pointer to the logon session ID for which a new logon track is 00561 to be created. 00562 00563 Return Value: 00564 00565 STATUS_SUCCESS - The logon session track was created successfully. 00566 00567 STATUS_LOGON_SESSION_EXISTS - The logon session already exists. 00568 A new one has not been created. 00569 00570 --*/ 00571 00572 { 00573 00574 ULONG SessionArrayIndex; 00575 PSEP_LOGON_SESSION_REFERENCES Previous, Current; 00576 PSEP_LOGON_SESSION_REFERENCES LogonSessionTrack; 00577 00578 PAGED_CODE(); 00579 00580 // 00581 // Make sure we can allocate a new logon session track record 00582 // 00583 00584 LogonSessionTrack = (PSEP_LOGON_SESSION_REFERENCES) 00585 ExAllocatePoolWithTag( 00586 PagedPool, 00587 sizeof(SEP_LOGON_SESSION_REFERENCES), 00588 'sLeS' 00589 ); 00590 00591 if (LogonSessionTrack == NULL) { 00592 return STATUS_INSUFFICIENT_RESOURCES; 00593 } 00594 00595 LogonSessionTrack->LogonId = (*LogonId); 00596 LogonSessionTrack->ReferenceCount = 0; 00597 00598 00599 00600 SessionArrayIndex = SepLogonSessionIndex( LogonId ); 00601 00602 // 00603 // Protect modification of reference monitor database 00604 // 00605 00606 SepRmAcquireDbWriteLock(); 00607 00608 00609 // 00610 // Now walk the list for our logon session array hash index 00611 // looking for a duplicate logon session ID. 00612 // 00613 00614 Previous = (PSEP_LOGON_SESSION_REFERENCES) 00615 ((PVOID)&SepLogonSessions[ SessionArrayIndex ]); 00616 Current = Previous->Next; 00617 00618 while (Current != NULL) { 00619 00620 if (RtlEqualLuid( LogonId, &Current->LogonId) ) { 00621 00622 // 00623 // One already exists. Hmmm. 00624 // 00625 00626 SepRmReleaseDbWriteLock(); 00627 ExFreePool(LogonSessionTrack); 00628 return STATUS_LOGON_SESSION_EXISTS; 00629 00630 } 00631 00632 Previous = Current; 00633 Current = Current->Next; 00634 } 00635 00636 00637 // 00638 // Reached the end of the list without finding a duplicate. 00639 // Add the new one. 00640 // 00641 00642 LogonSessionTrack->Next = SepLogonSessions[ SessionArrayIndex ]; 00643 SepLogonSessions[ SessionArrayIndex ] = LogonSessionTrack; 00644 00645 00646 00647 00648 SepRmReleaseDbWriteLock(); 00649 return STATUS_SUCCESS; 00650 00651 } 00652 00653 00654 NTSTATUS 00655 SepDeleteLogonSessionTrack( 00656 IN PLUID LogonId 00657 ) 00658 00659 /*++ 00660 00661 Routine Description: 00662 00663 This routine creates a new logon session tracking record. 00664 00665 This should only be called as a dispatch routine for a LSA->RM 00666 call (and once during system initialization). 00667 00668 If the specified logon session already exists, then an error is returned. 00669 00670 00671 00672 Arguments: 00673 00674 LogonId - Pointer to the logon session ID whose logon track is 00675 to be deleted. 00676 00677 Return Value: 00678 00679 STATUS_SUCCESS - The logon session track was deleted successfully. 00680 00681 STATUS_BAD_LOGON_SESSION_STATE - The logon session has a non-zero 00682 reference count and can not be deleted. 00683 00684 STATUS_NO_SUCH_LOGON_SESSION - The specified logon session does not 00685 exist. 00686 00687 00688 --*/ 00689 00690 { 00691 00692 ULONG SessionArrayIndex; 00693 PSEP_LOGON_SESSION_REFERENCES Previous, Current; 00694 00695 PAGED_CODE(); 00696 00697 SessionArrayIndex = SepLogonSessionIndex( LogonId ); 00698 00699 // 00700 // Protect modification of reference monitor database 00701 // 00702 00703 SepRmAcquireDbWriteLock(); 00704 00705 00706 // 00707 // Now walk the list for our logon session array hash index. 00708 // 00709 00710 Previous = (PSEP_LOGON_SESSION_REFERENCES) 00711 ((PVOID)&SepLogonSessions[ SessionArrayIndex ]); 00712 Current = Previous->Next; 00713 00714 while (Current != NULL) { 00715 00716 // 00717 // If we found it, make sure reference count is zero 00718 // 00719 00720 if (RtlEqualLuid( LogonId, &Current->LogonId) ) { 00721 00722 if (Current->ReferenceCount == 0) { 00723 00724 // 00725 // Pull it from the list 00726 // 00727 00728 Previous->Next = Current->Next; 00729 00730 00731 // 00732 // No longer need to protect our pointer to this 00733 // record. 00734 // 00735 00736 SepRmReleaseDbWriteLock(); 00737 00738 00739 // 00740 // Deallocate the logon session track record. 00741 // 00742 00743 ExFreePool( (PVOID)Current ); 00744 00745 00746 return STATUS_SUCCESS; 00747 00748 } 00749 00750 // 00751 // reference count was not zero. This is not considered 00752 // a healthy situation. Return an error and let someone 00753 // else declare the bug check. 00754 // 00755 00756 SepRmReleaseDbWriteLock(); 00757 return STATUS_BAD_LOGON_SESSION_STATE; 00758 } 00759 00760 Previous = Current; 00761 Current = Current->Next; 00762 } 00763 00764 SepRmReleaseDbWriteLock(); 00765 00766 // 00767 // Someone asked us to delete a logon session that isn't 00768 // in the database. 00769 // 00770 00771 return STATUS_NO_SUCH_LOGON_SESSION; 00772 00773 } 00774 00775 00776 VOID 00777 SepInformLsaOfDeletedLogon( 00778 IN PLUID LogonId 00779 ) 00780 00781 /*++ 00782 00783 Routine Description: 00784 00785 This routine informs the LSA about the deletion of a logon session. 00786 00787 Note that we can not be guaranteed that we are in a whole (or wholesome) 00788 thread, since we may be in the middle of process deletion and object 00789 rundown. Therefore, we must queue the work off to a worker thread which 00790 can then make an LPC call to the LSA. 00791 00792 00793 00794 00795 Arguments: 00796 00797 LogonId - Pointer to the logon session ID which has been deleted. 00798 00799 Return Value: 00800 00801 None. 00802 00803 --*/ 00804 00805 { 00806 PSEP_LSA_WORK_ITEM DeleteLogonItem; 00807 00808 PAGED_CODE(); 00809 00810 // 00811 // Pass the LUID value along with the work queue item. 00812 // Note that the worker thread is responsible for freeing the WorkItem data 00813 // structure. 00814 // 00815 00816 DeleteLogonItem = ExAllocatePoolWithTag( PagedPool, sizeof(SEP_LSA_WORK_ITEM), 'wLeS' ); 00817 if (DeleteLogonItem == NULL) { 00818 00819 // 00820 // I don't know what to do here... we loose track of a logon session, 00821 // but the system isn't really harmed in any way. 00822 // 00823 00824 return; 00825 00826 } 00827 00828 DeleteLogonItem->CommandParams.LogonId = (*LogonId); 00829 DeleteLogonItem->CommandNumber = LsapLogonSessionDeletedCommand; 00830 DeleteLogonItem->CommandParamsLength = sizeof( LUID ); 00831 DeleteLogonItem->ReplyBuffer = NULL; 00832 DeleteLogonItem->ReplyBufferLength = 0; 00833 DeleteLogonItem->CleanupFunction = NULL; 00834 DeleteLogonItem->CleanupParameter = 0; 00835 DeleteLogonItem->Tag = SepDeleteLogon; 00836 DeleteLogonItem->CommandParamsMemoryType = SepRmImmediateMemory; 00837 00838 if (!SepQueueWorkItem( DeleteLogonItem, TRUE )) { 00839 00840 ExFreePool( DeleteLogonItem ); 00841 } 00842 00843 return; 00844 00845 } 00846 00847 00848 NTSTATUS 00849 SeRegisterLogonSessionTerminatedRoutine( 00850 IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine 00851 ) 00852 00853 /*++ 00854 00855 Routine Description: 00856 00857 This routine is called by file systems that are interested in being 00858 notified when a logon session is being deleted. 00859 00860 Arguments: 00861 00862 CallbackRoutine - Address of routine to call back when a logon session 00863 is being deleted. 00864 00865 Return Value: 00866 00867 STATUS_SUCCESS - Successfully registered routine 00868 00869 STATUS_INVALID_PARAMETER - CallbackRoutine is NULL 00870 00871 STATUS_INSUFFICIENT_RESOURCE - Unable to allocate list entry. 00872 00873 --*/ 00874 00875 { 00876 PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION NewCallback; 00877 00878 PAGED_CODE(); 00879 00880 if (CallbackRoutine == NULL) { 00881 return( STATUS_INVALID_PARAMETER ); 00882 } 00883 00884 NewCallback = ExAllocatePoolWithTag( 00885 PagedPool, 00886 sizeof(SEP_LOGON_SESSION_TERMINATED_NOTIFICATION), 00887 'SFeS'); 00888 00889 if (NewCallback == NULL) { 00890 return( STATUS_INSUFFICIENT_RESOURCES ); 00891 } 00892 00893 SepRmAcquireDbWriteLock(); 00894 00895 NewCallback->Next = SeFileSystemNotifyRoutinesHead.Next; 00896 00897 NewCallback->CallbackRoutine = CallbackRoutine; 00898 00899 SeFileSystemNotifyRoutinesHead.Next = NewCallback; 00900 00901 SepRmReleaseDbWriteLock(); 00902 00903 return( STATUS_SUCCESS ); 00904 } 00905 00906 00907 NTSTATUS 00908 SeUnregisterLogonSessionTerminatedRoutine( 00909 IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine 00910 ) 00911 00912 /*++ 00913 00914 Routine Description: 00915 00916 This is the dual of SeRegisterLogonSessionTerminatedRoutine. A File System 00917 *MUST* call this before it is unloaded. 00918 00919 Arguments: 00920 00921 CallbackRoutine - Address of routine that was originally passed in to 00922 SeRegisterLogonSessionTerminatedRoutine. 00923 00924 Return Value: 00925 00926 STATUS_SUCCESS - Successfully removed callback routine 00927 00928 STATUS_INVALID_PARAMETER - CallbackRoutine is NULL 00929 00930 STATUS_NOT_FOUND - Didn't find and entry for CallbackRoutine 00931 00932 --*/ 00933 { 00934 NTSTATUS Status; 00935 PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION PreviousEntry; 00936 PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION NotifyEntry; 00937 00938 PAGED_CODE(); 00939 00940 if (CallbackRoutine == NULL) { 00941 return( STATUS_INVALID_PARAMETER ); 00942 } 00943 00944 SepRmAcquireDbWriteLock(); 00945 00946 for (PreviousEntry = &SeFileSystemNotifyRoutinesHead, 00947 NotifyEntry = SeFileSystemNotifyRoutinesHead.Next; 00948 NotifyEntry != NULL; 00949 PreviousEntry = NotifyEntry, 00950 NotifyEntry = NotifyEntry->Next) { 00951 00952 if (NotifyEntry->CallbackRoutine == CallbackRoutine) 00953 break; 00954 00955 } 00956 00957 if (NotifyEntry != NULL) { 00958 00959 PreviousEntry->Next = NotifyEntry->Next; 00960 00961 ExFreePool( NotifyEntry ); 00962 00963 Status = STATUS_SUCCESS; 00964 00965 } else { 00966 00967 Status = STATUS_NOT_FOUND; 00968 00969 } 00970 00971 SepRmReleaseDbWriteLock(); 00972 00973 return( Status ); 00974 00975 } 00976 00977 00978 NTSTATUS 00979 SeMarkLogonSessionForTerminationNotification( 00980 IN PLUID LogonId 00981 ) 00982 00983 /*++ 00984 00985 Routine Description: 00986 00987 File systems that have registered for logon-termination notification 00988 can mark logon sessions they are interested in for callback by calling 00989 this routine. 00990 00991 Arguments: 00992 00993 LogonId - The logon id for which the file system should be notified 00994 when the logon session is terminated. 00995 00996 Returns: 00997 00998 Nothing. 00999 01000 --*/ 01001 01002 { 01003 01004 ULONG SessionArrayIndex; 01005 PSEP_LOGON_SESSION_REFERENCES Previous, Current; 01006 01007 PAGED_CODE(); 01008 01009 SessionArrayIndex = SepLogonSessionIndex( LogonId ); 01010 01011 // 01012 // Protect modification of reference monitor database 01013 // 01014 01015 SepRmAcquireDbWriteLock(); 01016 01017 01018 // 01019 // Now walk the list for our logon session array hash index. 01020 // 01021 01022 Previous = (PSEP_LOGON_SESSION_REFERENCES) 01023 ((PVOID)&SepLogonSessions[ SessionArrayIndex ]); 01024 Current = Previous->Next; 01025 01026 while (Current != NULL) { 01027 01028 // 01029 // If we found it, decrement the reference count and return 01030 // 01031 01032 if (RtlEqualLuid( LogonId, &Current->LogonId) ) { 01033 Current->Flags |= SEP_TERMINATION_NOTIFY; 01034 break; 01035 } 01036 01037 Previous = Current; 01038 Current = Current->Next; 01039 } 01040 01041 SepRmReleaseDbWriteLock(); 01042 01043 return( (Current != NULL) ? STATUS_SUCCESS : STATUS_NOT_FOUND ); 01044 01045 } 01046 01047 01048 VOID 01049 SepInformFileSystemsOfDeletedLogon( 01050 IN PLUID LogonId 01051 ) 01052 01053 /*++ 01054 01055 Routine Description: 01056 01057 This routine informs interested file systems of a deleted logon. 01058 01059 Note that we can not be guaranteed that we are in a whole (or wholesome) 01060 thread, since we may be in the middle of process deletion and object 01061 rundown. Therefore, we must queue the work off to a worker thread. 01062 01063 01064 Arguments: 01065 01066 LogonId - Pointer to the logon session ID which has been deleted. 01067 01068 Return Value: 01069 01070 None. 01071 01072 --*/ 01073 01074 { 01075 PSEP_FILE_SYSTEM_NOTIFY_CONTEXT FSNotifyContext; 01076 01077 PAGED_CODE(); 01078 01079 FSNotifyContext = ExAllocatePoolWithTag( 01080 NonPagedPool, 01081 sizeof(SEP_FILE_SYSTEM_NOTIFY_CONTEXT), 01082 'SFeS'); 01083 01084 if (FSNotifyContext == NULL) { 01085 01086 // 01087 // I don't know what to do here... file systems will loose track of a 01088 // logon session, but the system isn't really harmed in any way. 01089 // 01090 01091 return; 01092 01093 } 01094 01095 FSNotifyContext->LogonId = *LogonId; 01096 01097 ExInitializeWorkItem( &FSNotifyContext->WorkItem, 01098 (PWORKER_THREAD_ROUTINE) SepNotifyFileSystems, 01099 (PVOID) FSNotifyContext); 01100 01101 ExQueueWorkItem( &FSNotifyContext->WorkItem, DelayedWorkQueue ); 01102 01103 } 01104 01105 01106 VOID 01107 SepNotifyFileSystems( 01108 IN PVOID Context 01109 ) 01110 { 01111 PSEP_FILE_SYSTEM_NOTIFY_CONTEXT FSNotifyContext = 01112 (PSEP_FILE_SYSTEM_NOTIFY_CONTEXT) Context; 01113 01114 PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION NextCallback; 01115 01116 PAGED_CODE(); 01117 01118 // 01119 // Protect modification of the list of FS callbacks. 01120 // 01121 01122 SepRmAcquireDbReadLock(); 01123 01124 NextCallback = SeFileSystemNotifyRoutinesHead.Next; 01125 01126 while (NextCallback != NULL) { 01127 01128 NextCallback->CallbackRoutine( &FSNotifyContext->LogonId ); 01129 01130 NextCallback = NextCallback->Next; 01131 } 01132 01133 SepRmReleaseDbReadLock(); 01134 01135 ExFreePool( FSNotifyContext ); 01136 } 01137

Generated on Sat May 15 19:41:40 2004 for test by doxygen 1.3.7