Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1137 lines
25 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. rmlogon.c
  5. Abstract:
  6. This module implements the kernel mode logon tracking performed by the
  7. reference monitor. Logon tracking is performed by keeping a count of
  8. how many tokens exist for each active logon in a system. When a logon
  9. session's reference count drops to zero, the LSA is notified so that
  10. authentication packages can clean up any related context data.
  11. Author:
  12. Jim Kelly (JimK) 21-April-1991
  13. Environment:
  14. Kernel mode only.
  15. Revision History:
  16. --*/
  17. //#define SEP_TRACK_LOGON_SESSION_REFS
  18. #include "rmp.h"
  19. #include <bugcodes.h>
  20. SEP_LOGON_SESSION_TERMINATED_NOTIFICATION
  21. SeFileSystemNotifyRoutinesHead = {0};
  22. ////////////////////////////////////////////////////////////////////////////
  23. // //
  24. // Internally defined data types //
  25. // //
  26. ////////////////////////////////////////////////////////////////////////////
  27. typedef struct _SEP_FILE_SYSTEM_NOTIFY_CONTEXT {
  28. WORK_QUEUE_ITEM WorkItem;
  29. LUID LogonId;
  30. } SEP_FILE_SYSTEM_NOTIFY_CONTEXT, *PSEP_FILE_SYSTEM_NOTIFY_CONTEXT;
  31. ////////////////////////////////////////////////////////////////////////////
  32. // //
  33. // Internally defined routines //
  34. // //
  35. ////////////////////////////////////////////////////////////////////////////
  36. NTSTATUS
  37. SepGetLogonSessionTrack(
  38. IN PLUID LogonId
  39. );
  40. VOID
  41. SepInformLsaOfDeletedLogon(
  42. IN PLUID LogonId
  43. );
  44. VOID
  45. SepInformFileSystemsOfDeletedLogon(
  46. IN PLUID LogonId
  47. );
  48. VOID
  49. SepNotifyFileSystems(
  50. IN PVOID Context
  51. );
  52. #ifdef ALLOC_PRAGMA
  53. #pragma alloc_text(PAGE,SeRegisterLogonSessionTerminatedRoutine)
  54. #pragma alloc_text(PAGE,SeUnregisterLogonSessionTerminatedRoutine)
  55. #pragma alloc_text(PAGE,SeMarkLogonSessionForTerminationNotification)
  56. #pragma alloc_text(PAGE,SepRmCreateLogonSessionWrkr)
  57. #pragma alloc_text(PAGE,SepRmDeleteLogonSessionWrkr)
  58. #pragma alloc_text(PAGE,SepReferenceLogonSession)
  59. #pragma alloc_text(PAGE,SepDeReferenceLogonSession)
  60. #pragma alloc_text(PAGE,SepCreateLogonSessionTrack)
  61. #pragma alloc_text(PAGE,SepDeleteLogonSessionTrack)
  62. #pragma alloc_text(PAGE,SepInformLsaOfDeletedLogon)
  63. #pragma alloc_text(PAGE,SepInformFileSystemsOfDeletedLogon)
  64. #pragma alloc_text(PAGE,SepNotifyFileSystems)
  65. #endif
  66. ////////////////////////////////////////////////////////////////////////////
  67. // //
  68. // Local macros //
  69. // //
  70. ////////////////////////////////////////////////////////////////////////////
  71. //
  72. // This macro is used to obtain an index into the logon session tracking
  73. // array given a logon session ID (a LUID).
  74. //
  75. #define SepLogonSessionIndex( PLogonId ) ( \
  76. (PLogonId)->LowPart & SEP_LOGON_TRACK_INDEX_MASK \
  77. )
  78. ////////////////////////////////////////////////////////////////////////////
  79. // //
  80. // Exported Services //
  81. // //
  82. ////////////////////////////////////////////////////////////////////////////
  83. VOID
  84. SepRmCreateLogonSessionWrkr(
  85. IN PRM_COMMAND_MESSAGE CommandMessage,
  86. OUT PRM_REPLY_MESSAGE ReplyMessage
  87. )
  88. /*++
  89. Routine Description:
  90. This function is the dispatch routine for the LSA --> RM
  91. "CreateLogonSession" call.
  92. The arguments passed to this routine are defined by the
  93. type SEP_RM_COMMAND_WORKER.
  94. Arguments:
  95. CommandMessage - Points to structure containing RM command message
  96. information consisting of an LPC PORT_MESSAGE structure followed
  97. by the command number (RmComponentTestCommand) and a command-specific
  98. body. The command-specific body of this parameter is a LUID of the
  99. logon session to be created.
  100. ReplyMessage - Pointer to structure containing LSA reply message
  101. information consisting of an LPC PORT_MESSAGE structure followed
  102. by the command ReturnedStatus field in which a status code from the
  103. command will be returned.
  104. Return Value:
  105. VOID
  106. --*/
  107. {
  108. NTSTATUS Status;
  109. LUID LogonId;
  110. PAGED_CODE();
  111. //
  112. // Check that command is expected type
  113. //
  114. ASSERT( CommandMessage->CommandNumber == RmCreateLogonSession );
  115. //
  116. // Typecast the command parameter to what we expect.
  117. //
  118. LogonId = *((LUID UNALIGNED *) CommandMessage->CommandParams);
  119. //
  120. // Try to create the logon session tracking record
  121. //
  122. Status = SepCreateLogonSessionTrack( &LogonId );
  123. //
  124. // Set the reply status
  125. //
  126. ReplyMessage->ReturnedStatus = Status;
  127. return;
  128. }
  129. VOID
  130. SepRmDeleteLogonSessionWrkr(
  131. IN PRM_COMMAND_MESSAGE CommandMessage,
  132. OUT PRM_REPLY_MESSAGE ReplyMessage
  133. )
  134. /*++
  135. Routine Description:
  136. This function is the dispatch routine for the LSA --> RM
  137. "DeleteLogonSession" call.
  138. The arguments passed to this routine are defined by the
  139. type SEP_RM_COMMAND_WORKER.
  140. Arguments:
  141. CommandMessage - Points to structure containing RM command message
  142. information consisting of an LPC PORT_MESSAGE structure followed
  143. by the command number (RmComponentTestCommand) and a command-specific
  144. body. The command-specific body of this parameter is a LUID of the
  145. logon session to be created.
  146. ReplyMessage - Pointer to structure containing LSA reply message
  147. information consisting of an LPC PORT_MESSAGE structure followed
  148. by the command ReturnedStatus field in which a status code from the
  149. command will be returned.
  150. Return Value:
  151. VOID
  152. --*/
  153. {
  154. NTSTATUS Status;
  155. LUID LogonId;
  156. PAGED_CODE();
  157. //
  158. // Check that command is expected type
  159. //
  160. ASSERT( CommandMessage->CommandNumber == RmDeleteLogonSession );
  161. //
  162. // Typecast the command parameter to what we expect.
  163. //
  164. LogonId = *((LUID UNALIGNED *) CommandMessage->CommandParams);
  165. //
  166. // Try to create the logon session tracking record
  167. //
  168. Status = SepDeleteLogonSessionTrack( &LogonId );
  169. //
  170. // Set the reply status
  171. //
  172. ReplyMessage->ReturnedStatus = Status;
  173. return;
  174. }
  175. NTSTATUS
  176. SepReferenceLogonSession(
  177. IN PLUID LogonId
  178. )
  179. /*++
  180. Routine Description:
  181. This routine increments the reference count of a logon session
  182. tracking record.
  183. Arguments:
  184. LogonId - Pointer to the logon session ID whose logon track is
  185. to be incremented.
  186. Return Value:
  187. STATUS_SUCCESS - The reference count was successfully incremented.
  188. STATUS_NO_SUCH_LOGON_SESSION - The specified logon session doesn't
  189. exist in the reference monitor's database.
  190. --*/
  191. {
  192. ULONG SessionArrayIndex;
  193. PSEP_LOGON_SESSION_REFERENCES Previous, Current;
  194. #ifdef SEP_TRACK_LOGON_SESSION_REFS
  195. ULONG Refs;
  196. #endif //SEP_TRACK_LOGON_SESSION_REFS
  197. PAGED_CODE();
  198. SessionArrayIndex = SepLogonSessionIndex( LogonId );
  199. //
  200. // Protect modification of reference monitor database
  201. //
  202. SepRmAcquireDbWriteLock();
  203. //
  204. // Now walk the list for our logon session array hash index.
  205. //
  206. Previous = (PSEP_LOGON_SESSION_REFERENCES)
  207. ((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
  208. Current = Previous->Next;
  209. while (Current != NULL) {
  210. //
  211. // If we found it, increment the reference count and return
  212. //
  213. if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
  214. #ifdef SEP_TRACK_LOGON_SESSION_REFS
  215. ULONG Refs;
  216. #endif //SEP_TRACK_LOGON_SESSION_REFS
  217. Current->ReferenceCount += 1;
  218. #ifdef SEP_TRACK_LOGON_SESSION_REFS
  219. Refs = Current->ReferenceCount;
  220. #endif //SEP_TRACK_LOGON_SESSION_REFS
  221. SepRmReleaseDbWriteLock();
  222. #ifdef SEP_TRACK_LOGON_SESSION_REFS
  223. DbgPrint("SE (rm): ++ logon session: (%d, %d) to %d by (%d, %d)\n",
  224. LogonId->HighPart, LogonId->LowPart, Refs,
  225. PsGetCurrentThread()->Cid.UniqueProcess,
  226. PsGetCurrentThread()->Cid.UniqueThread);
  227. #endif //SEP_TRACK_LOGON_SESSION_REFS
  228. return STATUS_SUCCESS;
  229. }
  230. Previous = Current;
  231. Current = Current->Next;
  232. }
  233. SepRmReleaseDbWriteLock();
  234. //
  235. // Bad news, someone asked us to increment the reference count of
  236. // a logon session we didn't know existed. This might be a new
  237. // token being created, so return an error status and let the caller
  238. // decide if it warrants a bug check or not.
  239. //
  240. return STATUS_NO_SUCH_LOGON_SESSION;
  241. }
  242. VOID
  243. SepDeReferenceLogonSession(
  244. IN PLUID LogonId
  245. )
  246. /*++
  247. Routine Description:
  248. This routine decrements the reference count of a logon session
  249. tracking record.
  250. If the reference count is decremented to zero, then there is no
  251. possibility for any more tokens to exist for the logon session.
  252. In this case, the LSA is notified that a logon session has
  253. terminated.
  254. Arguments:
  255. LogonId - Pointer to the logon session ID whose logon track is
  256. to be decremented.
  257. Return Value:
  258. None.
  259. --*/
  260. {
  261. ULONG SessionArrayIndex;
  262. PSEP_LOGON_SESSION_REFERENCES Previous, Current;
  263. #ifdef SEP_TRACK_LOGON_SESSION_REFS
  264. ULONG Refs;
  265. #endif //SEP_TRACK_LOGON_SESSION_REFS
  266. PAGED_CODE();
  267. SessionArrayIndex = SepLogonSessionIndex( LogonId );
  268. //
  269. // Protect modification of reference monitor database
  270. //
  271. SepRmAcquireDbWriteLock();
  272. //
  273. // Now walk the list for our logon session array hash index.
  274. //
  275. Previous = (PSEP_LOGON_SESSION_REFERENCES)
  276. ((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
  277. Current = Previous->Next;
  278. while (Current != NULL) {
  279. //
  280. // If we found it, decrement the reference count and return
  281. //
  282. if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
  283. Current->ReferenceCount -= 1;
  284. if (Current->ReferenceCount == 0) {
  285. //
  286. // Pull it from the list
  287. //
  288. Previous->Next = Current->Next;
  289. //
  290. // No longer need to protect our pointer to this
  291. // record.
  292. //
  293. SepRmReleaseDbWriteLock();
  294. //
  295. // Asynchronoously inform file systems that this logon session
  296. // is going away, if atleast one FS expressed interest in this
  297. // logon session.
  298. //
  299. if (Current->Flags & SEP_TERMINATION_NOTIFY) {
  300. SepInformFileSystemsOfDeletedLogon( LogonId );
  301. }
  302. //
  303. // Deallocate the logon session track record.
  304. //
  305. ExFreePool( (PVOID)Current );
  306. #ifdef SEP_TRACK_LOGON_SESSION_REFS
  307. DbgPrint("SE (rm): -- ** logon session: (%d, %d) to ZERO by (%d, %d)\n",
  308. LogonId->HighPart, LogonId->LowPart,
  309. PsGetCurrentThread()->Cid.UniqueProcess,
  310. PsGetCurrentThread()->Cid.UniqueThread);
  311. #endif //SEP_TRACK_LOGON_SESSION_REFS
  312. //
  313. // Inform the LSA about the deletion of this logon session.
  314. //
  315. SepInformLsaOfDeletedLogon( LogonId );
  316. return;
  317. }
  318. //
  319. // reference count was incremented, but not to zero.
  320. //
  321. #ifdef SEP_TRACK_LOGON_SESSION_REFS
  322. Refs = Current->ReferenceCount;
  323. #endif //SEP_TRACK_LOGON_SESSION_REFS
  324. SepRmReleaseDbWriteLock();
  325. #ifdef SEP_TRACK_LOGON_SESSION_REFS
  326. DbgPrint("SE (rm): -- logon session: (%d, %d) to %d by (%d, %d)\n",
  327. LogonId->HighPart, LogonId->LowPart, Refs,
  328. PsGetCurrentThread()->Cid.UniqueProcess,
  329. PsGetCurrentThread()->Cid.UniqueThread);
  330. #endif //SEP_TRACK_LOGON_SESSION_REFS
  331. return;
  332. }
  333. Previous = Current;
  334. Current = Current->Next;
  335. }
  336. SepRmReleaseDbWriteLock();
  337. //
  338. // Bad news, someone asked us to decrement the reference count of
  339. // a logon session we didn't know existed.
  340. //
  341. KeBugCheck( DEREF_UNKNOWN_LOGON_SESSION );
  342. return;
  343. }
  344. NTSTATUS
  345. SepCreateLogonSessionTrack(
  346. IN PLUID LogonId
  347. )
  348. /*++
  349. Routine Description:
  350. This routine creates a new logon session tracking record.
  351. This should only be called as a dispatch routine for a LSA->RM
  352. call (and once during system initialization).
  353. If the specified logon session already exists, then an error is returned.
  354. Arguments:
  355. LogonId - Pointer to the logon session ID for which a new logon track is
  356. to be created.
  357. Return Value:
  358. STATUS_SUCCESS - The logon session track was created successfully.
  359. STATUS_LOGON_SESSION_EXISTS - The logon session already exists.
  360. A new one has not been created.
  361. --*/
  362. {
  363. ULONG SessionArrayIndex;
  364. PSEP_LOGON_SESSION_REFERENCES Previous, Current;
  365. PSEP_LOGON_SESSION_REFERENCES LogonSessionTrack;
  366. PAGED_CODE();
  367. //
  368. // Make sure we can allocate a new logon session track record
  369. //
  370. LogonSessionTrack = (PSEP_LOGON_SESSION_REFERENCES)
  371. ExAllocatePoolWithTag(
  372. PagedPool,
  373. sizeof(SEP_LOGON_SESSION_REFERENCES),
  374. 'sLeS'
  375. );
  376. if (LogonSessionTrack == NULL) {
  377. return STATUS_INSUFFICIENT_RESOURCES;
  378. }
  379. LogonSessionTrack->LogonId = (*LogonId);
  380. LogonSessionTrack->ReferenceCount = 0;
  381. SessionArrayIndex = SepLogonSessionIndex( LogonId );
  382. //
  383. // Protect modification of reference monitor database
  384. //
  385. SepRmAcquireDbWriteLock();
  386. //
  387. // Now walk the list for our logon session array hash index
  388. // looking for a duplicate logon session ID.
  389. //
  390. Previous = (PSEP_LOGON_SESSION_REFERENCES)
  391. ((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
  392. Current = Previous->Next;
  393. while (Current != NULL) {
  394. if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
  395. //
  396. // One already exists. Hmmm.
  397. //
  398. SepRmReleaseDbWriteLock();
  399. ExFreePool(LogonSessionTrack);
  400. return STATUS_LOGON_SESSION_EXISTS;
  401. }
  402. Previous = Current;
  403. Current = Current->Next;
  404. }
  405. //
  406. // Reached the end of the list without finding a duplicate.
  407. // Add the new one.
  408. //
  409. LogonSessionTrack->Next = SepLogonSessions[ SessionArrayIndex ];
  410. SepLogonSessions[ SessionArrayIndex ] = LogonSessionTrack;
  411. SepRmReleaseDbWriteLock();
  412. return STATUS_SUCCESS;
  413. }
  414. NTSTATUS
  415. SepDeleteLogonSessionTrack(
  416. IN PLUID LogonId
  417. )
  418. /*++
  419. Routine Description:
  420. This routine creates a new logon session tracking record.
  421. This should only be called as a dispatch routine for a LSA->RM
  422. call (and once during system initialization).
  423. If the specified logon session already exists, then an error is returned.
  424. Arguments:
  425. LogonId - Pointer to the logon session ID whose logon track is
  426. to be deleted.
  427. Return Value:
  428. STATUS_SUCCESS - The logon session track was deleted successfully.
  429. STATUS_BAD_LOGON_SESSION_STATE - The logon session has a non-zero
  430. reference count and can not be deleted.
  431. STATUS_NO_SUCH_LOGON_SESSION - The specified logon session does not
  432. exist.
  433. --*/
  434. {
  435. ULONG SessionArrayIndex;
  436. PSEP_LOGON_SESSION_REFERENCES Previous, Current;
  437. PAGED_CODE();
  438. SessionArrayIndex = SepLogonSessionIndex( LogonId );
  439. //
  440. // Protect modification of reference monitor database
  441. //
  442. SepRmAcquireDbWriteLock();
  443. //
  444. // Now walk the list for our logon session array hash index.
  445. //
  446. Previous = (PSEP_LOGON_SESSION_REFERENCES)
  447. ((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
  448. Current = Previous->Next;
  449. while (Current != NULL) {
  450. //
  451. // If we found it, make sure reference count is zero
  452. //
  453. if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
  454. if (Current->ReferenceCount == 0) {
  455. //
  456. // Pull it from the list
  457. //
  458. Previous->Next = Current->Next;
  459. //
  460. // No longer need to protect our pointer to this
  461. // record.
  462. //
  463. SepRmReleaseDbWriteLock();
  464. //
  465. // Deallocate the logon session track record.
  466. //
  467. ExFreePool( (PVOID)Current );
  468. return STATUS_SUCCESS;
  469. }
  470. //
  471. // reference count was not zero. This is not considered
  472. // a healthy situation. Return an error and let someone
  473. // else declare the bug check.
  474. //
  475. SepRmReleaseDbWriteLock();
  476. return STATUS_BAD_LOGON_SESSION_STATE;
  477. }
  478. Previous = Current;
  479. Current = Current->Next;
  480. }
  481. SepRmReleaseDbWriteLock();
  482. //
  483. // Someone asked us to delete a logon session that isn't
  484. // in the database.
  485. //
  486. return STATUS_NO_SUCH_LOGON_SESSION;
  487. }
  488. VOID
  489. SepInformLsaOfDeletedLogon(
  490. IN PLUID LogonId
  491. )
  492. /*++
  493. Routine Description:
  494. This routine informs the LSA about the deletion of a logon session.
  495. Note that we can not be guaranteed that we are in a whole (or wholesome)
  496. thread, since we may be in the middle of process deletion and object
  497. rundown. Therefore, we must queue the work off to a worker thread which
  498. can then make an LPC call to the LSA.
  499. Arguments:
  500. LogonId - Pointer to the logon session ID which has been deleted.
  501. Return Value:
  502. None.
  503. --*/
  504. {
  505. PSEP_LSA_WORK_ITEM DeleteLogonItem;
  506. PAGED_CODE();
  507. //
  508. // Pass the LUID value along with the work queue item.
  509. // Note that the worker thread is responsible for freeing the WorkItem data
  510. // structure.
  511. //
  512. DeleteLogonItem = ExAllocatePoolWithTag( PagedPool, sizeof(SEP_LSA_WORK_ITEM), 'wLeS' );
  513. if (DeleteLogonItem == NULL) {
  514. //
  515. // I don't know what to do here... we loose track of a logon session,
  516. // but the system isn't really harmed in any way.
  517. //
  518. return;
  519. }
  520. DeleteLogonItem->CommandParams.LogonId = (*LogonId);
  521. DeleteLogonItem->CommandNumber = LsapLogonSessionDeletedCommand;
  522. DeleteLogonItem->CommandParamsLength = sizeof( LUID );
  523. DeleteLogonItem->ReplyBuffer = NULL;
  524. DeleteLogonItem->ReplyBufferLength = 0;
  525. DeleteLogonItem->CleanupFunction = NULL;
  526. DeleteLogonItem->CleanupParameter = 0;
  527. DeleteLogonItem->Tag = SepDeleteLogon;
  528. DeleteLogonItem->CommandParamsMemoryType = SepRmImmediateMemory;
  529. if (!SepQueueWorkItem( DeleteLogonItem, TRUE )) {
  530. ExFreePool( DeleteLogonItem );
  531. }
  532. return;
  533. }
  534. NTSTATUS
  535. SeRegisterLogonSessionTerminatedRoutine(
  536. IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine
  537. )
  538. /*++
  539. Routine Description:
  540. This routine is called by file systems that are interested in being
  541. notified when a logon session is being deleted.
  542. Arguments:
  543. CallbackRoutine - Address of routine to call back when a logon session
  544. is being deleted.
  545. Return Value:
  546. STATUS_SUCCESS - Successfully registered routine
  547. STATUS_INVALID_PARAMETER - CallbackRoutine is NULL
  548. STATUS_INSUFFICIENT_RESOURCE - Unable to allocate list entry.
  549. --*/
  550. {
  551. PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION NewCallback;
  552. PAGED_CODE();
  553. if (CallbackRoutine == NULL) {
  554. return( STATUS_INVALID_PARAMETER );
  555. }
  556. NewCallback = ExAllocatePoolWithTag(
  557. PagedPool,
  558. sizeof(SEP_LOGON_SESSION_TERMINATED_NOTIFICATION),
  559. 'SFeS');
  560. if (NewCallback == NULL) {
  561. return( STATUS_INSUFFICIENT_RESOURCES );
  562. }
  563. SepRmAcquireDbWriteLock();
  564. NewCallback->Next = SeFileSystemNotifyRoutinesHead.Next;
  565. NewCallback->CallbackRoutine = CallbackRoutine;
  566. SeFileSystemNotifyRoutinesHead.Next = NewCallback;
  567. SepRmReleaseDbWriteLock();
  568. return( STATUS_SUCCESS );
  569. }
  570. NTSTATUS
  571. SeUnregisterLogonSessionTerminatedRoutine(
  572. IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine
  573. )
  574. /*++
  575. Routine Description:
  576. This is the dual of SeRegisterLogonSessionTerminatedRoutine. A File System
  577. *MUST* call this before it is unloaded.
  578. Arguments:
  579. CallbackRoutine - Address of routine that was originally passed in to
  580. SeRegisterLogonSessionTerminatedRoutine.
  581. Return Value:
  582. STATUS_SUCCESS - Successfully removed callback routine
  583. STATUS_INVALID_PARAMETER - CallbackRoutine is NULL
  584. STATUS_NOT_FOUND - Didn't find and entry for CallbackRoutine
  585. --*/
  586. {
  587. NTSTATUS Status;
  588. PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION PreviousEntry;
  589. PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION NotifyEntry;
  590. PAGED_CODE();
  591. if (CallbackRoutine == NULL) {
  592. return( STATUS_INVALID_PARAMETER );
  593. }
  594. SepRmAcquireDbWriteLock();
  595. for (PreviousEntry = &SeFileSystemNotifyRoutinesHead,
  596. NotifyEntry = SeFileSystemNotifyRoutinesHead.Next;
  597. NotifyEntry != NULL;
  598. PreviousEntry = NotifyEntry,
  599. NotifyEntry = NotifyEntry->Next) {
  600. if (NotifyEntry->CallbackRoutine == CallbackRoutine)
  601. break;
  602. }
  603. if (NotifyEntry != NULL) {
  604. PreviousEntry->Next = NotifyEntry->Next;
  605. ExFreePool( NotifyEntry );
  606. Status = STATUS_SUCCESS;
  607. } else {
  608. Status = STATUS_NOT_FOUND;
  609. }
  610. SepRmReleaseDbWriteLock();
  611. return( Status );
  612. }
  613. NTSTATUS
  614. SeMarkLogonSessionForTerminationNotification(
  615. IN PLUID LogonId
  616. )
  617. /*++
  618. Routine Description:
  619. File systems that have registered for logon-termination notification
  620. can mark logon sessions they are interested in for callback by calling
  621. this routine.
  622. Arguments:
  623. LogonId - The logon id for which the file system should be notified
  624. when the logon session is terminated.
  625. Returns:
  626. Nothing.
  627. --*/
  628. {
  629. ULONG SessionArrayIndex;
  630. PSEP_LOGON_SESSION_REFERENCES Previous, Current;
  631. PAGED_CODE();
  632. SessionArrayIndex = SepLogonSessionIndex( LogonId );
  633. //
  634. // Protect modification of reference monitor database
  635. //
  636. SepRmAcquireDbWriteLock();
  637. //
  638. // Now walk the list for our logon session array hash index.
  639. //
  640. Previous = (PSEP_LOGON_SESSION_REFERENCES)
  641. ((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
  642. Current = Previous->Next;
  643. while (Current != NULL) {
  644. //
  645. // If we found it, decrement the reference count and return
  646. //
  647. if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
  648. Current->Flags |= SEP_TERMINATION_NOTIFY;
  649. break;
  650. }
  651. Previous = Current;
  652. Current = Current->Next;
  653. }
  654. SepRmReleaseDbWriteLock();
  655. return( (Current != NULL) ? STATUS_SUCCESS : STATUS_NOT_FOUND );
  656. }
  657. VOID
  658. SepInformFileSystemsOfDeletedLogon(
  659. IN PLUID LogonId
  660. )
  661. /*++
  662. Routine Description:
  663. This routine informs interested file systems of a deleted logon.
  664. Note that we can not be guaranteed that we are in a whole (or wholesome)
  665. thread, since we may be in the middle of process deletion and object
  666. rundown. Therefore, we must queue the work off to a worker thread.
  667. Arguments:
  668. LogonId - Pointer to the logon session ID which has been deleted.
  669. Return Value:
  670. None.
  671. --*/
  672. {
  673. PSEP_FILE_SYSTEM_NOTIFY_CONTEXT FSNotifyContext;
  674. PAGED_CODE();
  675. FSNotifyContext = ExAllocatePoolWithTag(
  676. NonPagedPool,
  677. sizeof(SEP_FILE_SYSTEM_NOTIFY_CONTEXT),
  678. 'SFeS');
  679. if (FSNotifyContext == NULL) {
  680. //
  681. // I don't know what to do here... file systems will loose track of a
  682. // logon session, but the system isn't really harmed in any way.
  683. //
  684. return;
  685. }
  686. FSNotifyContext->LogonId = *LogonId;
  687. ExInitializeWorkItem( &FSNotifyContext->WorkItem,
  688. (PWORKER_THREAD_ROUTINE) SepNotifyFileSystems,
  689. (PVOID) FSNotifyContext);
  690. ExQueueWorkItem( &FSNotifyContext->WorkItem, DelayedWorkQueue );
  691. }
  692. VOID
  693. SepNotifyFileSystems(
  694. IN PVOID Context
  695. )
  696. {
  697. PSEP_FILE_SYSTEM_NOTIFY_CONTEXT FSNotifyContext =
  698. (PSEP_FILE_SYSTEM_NOTIFY_CONTEXT) Context;
  699. PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION NextCallback;
  700. PAGED_CODE();
  701. //
  702. // Protect modification of the list of FS callbacks.
  703. //
  704. SepRmAcquireDbReadLock();
  705. NextCallback = SeFileSystemNotifyRoutinesHead.Next;
  706. while (NextCallback != NULL) {
  707. NextCallback->CallbackRoutine( &FSNotifyContext->LogonId );
  708. NextCallback = NextCallback->Next;
  709. }
  710. SepRmReleaseDbReadLock();
  711. ExFreePool( FSNotifyContext );
  712. }