Leaked source code of windows server 2003
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.

1009 lines
24 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: scavenge.c
  7. //
  8. // Contents: Home of the LSA scavenger thread
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 6-08-93 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <lsapch.hxx>
  18. #include "scavenge.hxx"
  19. #define SCAV_INTERNAL_NO_TRACE 0x10000000
  20. ULONG ScavNotifyCount;
  21. LIST_ENTRY NotifyList ;
  22. LIST_ENTRY NotifyEvents ;
  23. LIST_ENTRY ScavList ;
  24. RTL_CRITICAL_SECTION NotifyLock ;
  25. RTL_CRITICAL_SECTION ScavLock ;
  26. HKEY LsaRegistryKey ;
  27. HANDLE LsaRegistryWatchEvent ;
  28. #define SCAV_TABLE 8
  29. PVOID DeadScavItems[ SCAV_TABLE ];
  30. ULONG DeadScavIndex ;
  31. #define SCAVENGER_WAIT_INTERVAL 60000L
  32. //
  33. // Internal flags:
  34. //
  35. #define SCAVFLAG_NOTIFY_EVENT 0x01000000
  36. #define SCAVFLAG_ASYNC_TIMER_DELETE 0x00400000
  37. #define NOTIFY_FLAG_SYNCHRONOUS 0x00000001
  38. #define LockScavenger() RtlEnterCriticalSection( &ScavLock )
  39. #define UnlockScavenger() RtlLeaveCriticalSection( &ScavLock )
  40. #define LockNotify() RtlEnterCriticalSection( &NotifyLock )
  41. #define UnlockNotify() RtlLeaveCriticalSection( &NotifyLock )
  42. //
  43. // Define locking macros for the scav list
  44. //
  45. #define LsapRefScavItem( Item ) \
  46. { \
  47. RtlEnterCriticalSection( &ScavLock ); \
  48. ((PLSAP_SCAVENGER_ITEM) Item)->RefCount++ ; \
  49. RtlLeaveCriticalSection( &ScavLock ); \
  50. }
  51. #define LsapRefScavItemUnsafe( Item ) \
  52. { \
  53. ((PLSAP_SCAVENGER_ITEM) Item)->RefCount++ ; \
  54. }
  55. DWORD
  56. WINAPI
  57. LsapScavengerThread(
  58. PVOID Ignored
  59. );
  60. BOOLEAN LsapBreakEveryMinute = FALSE;
  61. BOOLEAN LsapDebuggerOk = FALSE ;
  62. VOID
  63. FreeScavengerItem(
  64. IN PLSAP_SCAVENGER_ITEM Item
  65. )
  66. {
  67. ASSERT( Item->List.Flink == NULL );
  68. ASSERT( Item->PackageList.Flink == NULL );
  69. LsapFreePrivateHeap( Item );
  70. }
  71. VOID
  72. LsapInternalBreak(
  73. VOID
  74. )
  75. {
  76. if ( !LsapDebuggerOk )
  77. {
  78. return;
  79. }
  80. DbgBreakPoint();
  81. }
  82. ULONG
  83. NTAPI
  84. LsapScavengerBreak(
  85. PVOID Param
  86. )
  87. {
  88. if (LsapBreakEveryMinute)
  89. {
  90. LsapInternalBreak();
  91. }
  92. HANDLE hToken;
  93. DWORD ReturnLength;
  94. TOKEN_STATISTICS TokenStats;
  95. NTSTATUS Status;
  96. Status = NtOpenProcessToken(
  97. NtCurrentProcess(),
  98. TOKEN_QUERY,
  99. &hToken
  100. );
  101. if (NT_SUCCESS( Status )) {
  102. Status = NtQueryInformationToken (
  103. hToken,
  104. TokenStatistics,
  105. &TokenStats,
  106. sizeof( TOKEN_STATISTICS ),
  107. &ReturnLength
  108. );
  109. if (NT_SUCCESS( Status )) {
  110. if (TokenStats.ExpirationTime.QuadPart == 0i64) {
  111. LsapInternalBreak();
  112. }
  113. }
  114. NtClose( hToken );
  115. }
  116. return(0);
  117. }
  118. //+---------------------------------------------------------------------------
  119. //
  120. // Function: LsapRegistryWatch
  121. //
  122. // Synopsis: Callback that handles registry changes in the LSA key
  123. //
  124. // Arguments: [Ignored]
  125. //
  126. // History: 05-10-00 RichardW
  127. //
  128. // Notes:
  129. //
  130. //----------------------------------------------------------------------------
  131. DWORD
  132. LsapRegistryWatch(
  133. PVOID Ignored
  134. )
  135. {
  136. //
  137. // refresh dynamically changable parameters.
  138. //
  139. LoadParameters( TRUE );
  140. RegNotifyChangeKeyValue(
  141. LsaRegistryKey,
  142. TRUE,
  143. REG_NOTIFY_CHANGE_NAME |
  144. REG_NOTIFY_CHANGE_LAST_SET,
  145. LsaRegistryWatchEvent,
  146. TRUE );
  147. LsapEventNotify(
  148. NOTIFY_CLASS_REGISTRY_CHANGE,
  149. 0,
  150. 0,
  151. NULL );
  152. return 0 ;
  153. }
  154. //+---------------------------------------------------------------------------
  155. //
  156. // Function: LsapDerefScavItem
  157. //
  158. // Synopsis: Dereference, optionally freeing a scavenger item
  159. //
  160. // Arguments: [Item] --
  161. //
  162. // History: 6-03-97 RichardW Created
  163. //
  164. // Notes:
  165. //
  166. //----------------------------------------------------------------------------
  167. VOID
  168. LsapDerefScavItem(
  169. PLSAP_SCAVENGER_ITEM Item
  170. )
  171. {
  172. HANDLE TimerDeleteHandle ;
  173. LockScavenger();
  174. Item->RefCount-- ;
  175. if ( Item->RefCount == 0 )
  176. {
  177. DebugLog(( DEB_TRACE_SCAV, "Removing item %x\n", Item ));
  178. if ( Item->List.Flink )
  179. {
  180. RemoveEntryList( &Item->List );
  181. Item->List.Flink = NULL ;
  182. }
  183. if ( Item->PackageList.Flink )
  184. {
  185. RemoveEntryList( &Item->PackageList );
  186. Item->PackageList.Flink = NULL ;
  187. }
  188. //
  189. // Because the rtl thread pool is asynchronous to this one,
  190. // we need to keep track of recently deceased scavenger items
  191. // to prevent them from being used in an RTL thread. The add
  192. // function will scan the table to remove any potential duplicates.
  193. //
  194. DeadScavItems[ DeadScavIndex ] = Item ;
  195. DeadScavIndex ++ ;
  196. DeadScavIndex &= (SCAV_TABLE - 1);
  197. UnlockScavenger();
  198. if ( Item->Type == NOTIFIER_TYPE_INTERVAL )
  199. {
  200. //
  201. // Kill the timerq handle:
  202. //
  203. if ( Item->TimerHandle != INVALID_HANDLE_VALUE &&
  204. Item->TimerHandle != NULL )
  205. {
  206. if ( (Item->Flags & SCAVFLAG_ASYNC_TIMER_DELETE) != 0 )
  207. {
  208. TimerDeleteHandle = 0 ;
  209. }
  210. else
  211. {
  212. TimerDeleteHandle = INVALID_HANDLE_VALUE ;
  213. }
  214. DeleteTimerQueueTimer( NULL,
  215. Item->TimerHandle,
  216. TimerDeleteHandle );
  217. }
  218. }
  219. else if ( Item->Type == NOTIFIER_TYPE_HANDLE_WAIT )
  220. {
  221. if ( Item->TimerHandle != INVALID_HANDLE_VALUE &&
  222. Item->TimerHandle != NULL )
  223. {
  224. UnregisterWaitEx( Item->TimerHandle,
  225. INVALID_HANDLE_VALUE );
  226. }
  227. }
  228. if ( ( Item->Type != NOTIFIER_TYPE_NOTIFY_EVENT ) &&
  229. ( Item->Type != NOTIFIER_TYPE_IMMEDIATE ) )
  230. {
  231. //
  232. // Yield to let the other thread remove the item
  233. //
  234. Sleep( 100 );
  235. }
  236. Item->ScavCheck = SCAVMAGIC_FREE ;
  237. FreeScavengerItem( Item );
  238. }
  239. else
  240. {
  241. UnlockScavenger();
  242. }
  243. }
  244. //+---------------------------------------------------------------------------
  245. //
  246. // Function: LsapScavengerTrigger
  247. //
  248. // Synopsis: Actual Trigger
  249. //
  250. // Arguments: [Parameter] -- Item to call
  251. //
  252. // History: 5-24-97 RichardW Created
  253. //
  254. // Notes:
  255. //
  256. //----------------------------------------------------------------------------
  257. ULONG
  258. LsapScavengerTrigger(
  259. PVOID Parameter
  260. )
  261. {
  262. PLSAP_SCAVENGER_ITEM Item ;
  263. #ifdef LSAP_VERIFY_PACKAGE_ID
  264. ULONG_PTR dwPackageID, dwCurId;
  265. #endif
  266. if ( ShutdownBegun )
  267. {
  268. return 0;
  269. }
  270. SetCurrentSession( pDefaultSession );
  271. Item = (PLSAP_SCAVENGER_ITEM) Parameter ;
  272. DsysAssert( Item->ScavCheck == SCAVMAGIC_ACTIVE );
  273. __try
  274. {
  275. #ifdef LSAP_VERIFY_PACKAGE_ID
  276. dwPackageID = Item->PackageId;
  277. dwCurId = GetCurrentPackageId();
  278. if ((dwCurId != SPMGR_ID) || (dwPackageID != SPMGR_ID))
  279. #endif
  280. {
  281. SetCurrentPackageId( Item->PackageId );
  282. }
  283. (VOID) Item->Function( Item->Parameter );
  284. #ifdef LSAP_VERIFY_PACKAGE_ID
  285. if (dwPackageID != SPMGR_ID)
  286. #endif
  287. {
  288. SetCurrentPackageId( SPMGR_ID );
  289. }
  290. }
  291. __except( SP_EXCEPTION )
  292. {
  293. SPException( GetExceptionCode(), Item->PackageId );
  294. }
  295. LsapDerefScavItem( Item );
  296. return 0 ;
  297. }
  298. //+---------------------------------------------------------------------------
  299. //
  300. // Function: LsapTimerCallback
  301. //
  302. // Synopsis: Callback from thread pool for scavenger items
  303. //
  304. // Arguments: [Context] --
  305. // [Timeout] --
  306. //
  307. // History: 7-01-98 RichardW Created
  308. //
  309. // Notes:
  310. //
  311. //----------------------------------------------------------------------------
  312. VOID
  313. LsapTimerCallback(
  314. PVOID Context,
  315. BOOLEAN Timeout
  316. )
  317. {
  318. PLSAP_SCAVENGER_ITEM Item ;
  319. ULONG i ;
  320. BOOL OneShot ;
  321. SetCurrentSession( pDefaultSession );
  322. Item = (PLSAP_SCAVENGER_ITEM) Context ;
  323. //
  324. // We only scan for handle and timer events. Things executed
  325. // by QueueUserWorkItem don't end up in this list, but that's
  326. // okay, since those items go directly to LsapScavengerTrigger
  327. //
  328. LockScavenger();
  329. for ( i = 0 ; i < SCAV_TABLE ; i++ )
  330. {
  331. if ( DeadScavItems[ i ] == Item )
  332. {
  333. break;
  334. }
  335. }
  336. if ( i != SCAV_TABLE )
  337. {
  338. //
  339. // uh oh, a dead one that was still in the queue in this
  340. // rtl worker thread. Ignore it.
  341. //
  342. UnlockScavenger();
  343. return ;
  344. }
  345. if ( Item->Flags & SCAVFLAG_ASYNC_TIMER_DELETE )
  346. {
  347. //
  348. // This is a bad condition. An item that should have
  349. // been fired once has shown up again. Ignore it.
  350. //
  351. UnlockScavenger();
  352. return;
  353. }
  354. LsapRefScavItemUnsafe( Item );
  355. OneShot = ( Item->Flags & NOTIFIER_FLAG_ONE_SHOT ) != 0 ;
  356. if ( OneShot )
  357. {
  358. //
  359. // This flag has the side effect of preventing further
  360. // callbacks. That lets us delete is asynchronously later.
  361. //
  362. Item->Flags |= SCAVFLAG_ASYNC_TIMER_DELETE ;
  363. }
  364. UnlockScavenger();
  365. if ( (Item->Flags & SCAV_INTERNAL_NO_TRACE ) == 0 )
  366. {
  367. DebugLog(( DEB_TRACE_SCAV, "Triggering item %x, type %d\n",
  368. Item, Item->Type ));
  369. }
  370. LsapScavengerTrigger( Item );
  371. //
  372. // If this is a one-shot item that's in the list, then it was
  373. // a delayed or otherwise "real" one-shot. Deref it again to
  374. // kill it.
  375. //
  376. if ( OneShot )
  377. {
  378. LsapDerefScavItem( Item );
  379. }
  380. }
  381. //+---------------------------------------------------------------------------
  382. //
  383. // Function: LsapScavengerHandleNotify
  384. //
  385. // Synopsis: Called whenever a notification event goes off.
  386. //
  387. // Arguments: [Ignored] --
  388. //
  389. // History: 5-23-97 RichardW Created
  390. //
  391. // Notes:
  392. //
  393. //----------------------------------------------------------------------------
  394. DWORD
  395. WINAPI
  396. LsapScavengerHandleNotify(
  397. PVOID Ignored
  398. )
  399. {
  400. PLIST_ENTRY NotifyScan ;
  401. PLIST_ENTRY EventScan ;
  402. PLSAP_NOTIFY_EVENT Event ;
  403. PLSAP_SCAVENGER_ITEM Item ;
  404. do
  405. {
  406. LockNotify();
  407. if ( !IsListEmpty( &NotifyEvents ) )
  408. {
  409. EventScan = RemoveHeadList( &NotifyEvents );
  410. }
  411. else
  412. {
  413. EventScan = NULL ;
  414. }
  415. UnlockNotify();
  416. if ( EventScan )
  417. {
  418. Event = CONTAINING_RECORD( EventScan, LSAP_NOTIFY_EVENT, List );
  419. LockScavenger();
  420. NotifyScan = NotifyList.Flink ;
  421. while ( NotifyScan != &NotifyList )
  422. {
  423. Item = CONTAINING_RECORD( NotifyScan, LSAP_SCAVENGER_ITEM, List );
  424. if ( Item->Class == Event->Notify.EventClass )
  425. {
  426. Event->Notify.PackageParameter = Item->Parameter ;
  427. Item->Function( &Event->Notify );
  428. }
  429. NotifyScan = NotifyScan->Flink ;
  430. }
  431. UnlockScavenger();
  432. if ( Event->Flags & NOTIFY_FLAG_SYNCHRONOUS )
  433. {
  434. SetEvent( Event->hSync );
  435. }
  436. LsapFreeLsaHeap( Event );
  437. }
  438. } while ( EventScan );
  439. return 0 ;
  440. }
  441. //+---------------------------------------------------------------------------
  442. //
  443. // Function: LsaIRegisterNotification
  444. //
  445. // Synopsis: Registers a callback, to be called on either a handle signalled,
  446. // or an time based interval, or special async events
  447. //
  448. // Arguments: [pFunction] -- Callback function
  449. // [pvParameter] -- Parameter to pass
  450. // [Type] -- Type of callback
  451. // [Class] -- Event class
  452. // [fItem] -- Flags
  453. // [Interval] -- Interval to call
  454. // [hEvent] -- Handle to wait on
  455. //
  456. // History: 6-03-97 RichardW Created
  457. //
  458. // Notes:
  459. //
  460. //----------------------------------------------------------------------------
  461. PVOID
  462. NTAPI
  463. LsaIRegisterNotification(
  464. IN LPTHREAD_START_ROUTINE pFunction,
  465. IN PVOID pvParameter,
  466. IN ULONG Type,
  467. IN ULONG Class,
  468. IN ULONG fItem,
  469. IN ULONG Interval,
  470. IN HANDLE hEvent)
  471. {
  472. PLSAP_SCAVENGER_ITEM Item ;
  473. PLIST_ENTRY List = NULL ;
  474. BOOL Success ;
  475. DWORD DueTime ;
  476. ULONG i;
  477. Item = (PLSAP_SCAVENGER_ITEM) LsapAllocatePrivateHeap(
  478. sizeof( LSAP_SCAVENGER_ITEM ) );
  479. if ( !Item )
  480. {
  481. return NULL ;
  482. }
  483. Item->List.Flink = NULL ;
  484. Item->PackageList.Flink = NULL ;
  485. Item->Type = Type ;
  486. Item->Function = pFunction ;
  487. Item->Parameter = pvParameter ;
  488. Item->RefCount = 1 ;
  489. Item->PackageId = GetCurrentPackageId();
  490. Item->ScavCheck = SCAVMAGIC_ACTIVE;
  491. Item->Flags = fItem ;
  492. Item->TimerHandle = INVALID_HANDLE_VALUE;
  493. //
  494. // Okay, we have set up the item, more or less. Now, insert it
  495. // into the list we have selected for it.
  496. //
  497. DebugLog(( DEB_TRACE_SCAV, "Created scavenger item %x, type %d\n",
  498. Item, Item->Type ));
  499. switch ( Type )
  500. {
  501. case NOTIFIER_TYPE_IMMEDIATE:
  502. Item->Flags |= NOTIFIER_FLAG_ONE_SHOT ;
  503. Success = QueueUserWorkItem( LsapScavengerTrigger,
  504. Item,
  505. FALSE );
  506. //
  507. // And that's all. the item may in fact be freed by now, since the
  508. // worker thread could have completed. So, return success now,
  509. //
  510. return (Item);
  511. break;
  512. case NOTIFIER_TYPE_INTERVAL:
  513. case NOTIFIER_TYPE_HANDLE_WAIT:
  514. LockScavenger();
  515. InsertTailList( &ScavList, &Item->List );
  516. //
  517. // Make sure this pointer doesn't show up in the list of dead ones.
  518. // this can happen due to heap reuse.
  519. //
  520. for ( i = 0 ; i < SCAV_TABLE ; i++ )
  521. {
  522. if ( DeadScavItems[ i ] == Item )
  523. {
  524. DeadScavItems[ i ] = NULL ;
  525. }
  526. }
  527. UnlockScavenger();
  528. if ( Type == NOTIFIER_TYPE_INTERVAL )
  529. {
  530. if ( fItem & NOTIFIER_FLAG_SECONDS )
  531. {
  532. Interval *= 60 ;
  533. }
  534. Interval *= 1000 ;
  535. Success = CreateTimerQueueTimer(
  536. &Item->TimerHandle,
  537. NULL,
  538. LsapTimerCallback,
  539. Item,
  540. Interval,
  541. (fItem & NOTIFIER_FLAG_ONE_SHOT ?
  542. 0 : Interval ),
  543. 0 );
  544. }
  545. else
  546. {
  547. ASSERT( Type == NOTIFIER_TYPE_HANDLE_WAIT );
  548. Item->TimerHandle = RegisterWaitForSingleObjectEx(
  549. hEvent,
  550. LsapTimerCallback,
  551. Item,
  552. INFINITE,
  553. (fItem & NOTIFIER_FLAG_NEW_THREAD ?
  554. 0 : WT_EXECUTEINWAITTHREAD ) );
  555. Success = (Item->TimerHandle != NULL);
  556. }
  557. if ( !Success )
  558. {
  559. LsapDerefScavItem( Item );
  560. return NULL ;
  561. }
  562. break;
  563. case NOTIFIER_TYPE_NOTIFY_EVENT:
  564. Item->Class = Class ;
  565. Item->Flags |= SCAVFLAG_NOTIFY_EVENT ;
  566. LockScavenger();
  567. InsertTailList( &NotifyList, &Item->List );
  568. UnlockScavenger();
  569. Success = TRUE ;
  570. break;
  571. default:
  572. Success = FALSE ;
  573. FreeScavengerItem( Item );
  574. break;
  575. }
  576. return Item ;
  577. }
  578. //+---------------------------------------------------------------------------
  579. //
  580. // Function: LsaICancelNotification
  581. //
  582. // Arguments: [pvScavHandle] --
  583. //
  584. // History: 5-26-97 RichardW Created
  585. //
  586. // Notes:
  587. //
  588. //----------------------------------------------------------------------------
  589. NTSTATUS
  590. NTAPI
  591. LsaICancelNotification(
  592. PVOID pvScavHandle
  593. )
  594. {
  595. PLSAP_SCAVENGER_ITEM Item ;
  596. Item = (PLSAP_SCAVENGER_ITEM) pvScavHandle ;
  597. if ( Item->ScavCheck != SCAVMAGIC_ACTIVE )
  598. {
  599. return STATUS_INVALID_PARAMETER ;
  600. }
  601. LsapDerefScavItem( Item );
  602. return STATUS_SUCCESS ;
  603. }
  604. //+---------------------------------------------------------------------------
  605. //
  606. // Function: LsapEventNotify
  607. //
  608. // Synopsis: Notify waiters of a security package event
  609. //
  610. // Arguments: [Class] -- Event Class
  611. // [Flags] -- Flags
  612. // [EventSize] -- Size of event data
  613. // [EventData] -- ptr to event data
  614. //
  615. // History: 5-26-97 RichardW Created
  616. //
  617. // Notes:
  618. //
  619. //----------------------------------------------------------------------------
  620. BOOLEAN
  621. NTAPI
  622. LsapEventNotify(
  623. ULONG Class,
  624. ULONG Flags,
  625. ULONG EventSize,
  626. PVOID EventData)
  627. {
  628. PLSAP_NOTIFY_EVENT Event ;
  629. HANDLE hEvent = NULL;
  630. Event = (PLSAP_NOTIFY_EVENT) LsapAllocateLsaHeap( sizeof( LSAP_NOTIFY_EVENT ) + EventSize );
  631. if (Event)
  632. {
  633. Event->Notify.EventClass = Class;
  634. Event->Notify.EventDataSize = EventSize;
  635. Event->Notify.EventData = (PUCHAR) ( Event + 1 );
  636. RtlCopyMemory( Event->Notify.EventData,
  637. EventData,
  638. EventSize );
  639. Event->Flags = Flags;
  640. if (Flags & NOTIFY_FLAG_SYNCHRONOUS)
  641. {
  642. hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  643. Event->hSync = hEvent ;
  644. if (!Event->hSync)
  645. {
  646. LsapFreeLsaHeap( Event );
  647. return(FALSE);
  648. }
  649. }
  650. else
  651. {
  652. Event->hSync = NULL ;
  653. }
  654. //
  655. // Insert event into list
  656. //
  657. LockNotify();
  658. InsertTailList( &NotifyEvents, &Event->List );
  659. UnlockNotify();
  660. DebugLog((DEB_TRACE_SCAV, "EventNotify( %d ) - Data at %x\n",
  661. Class, Event->Notify.EventData ));
  662. //
  663. // Wake up the scavenger thread
  664. //
  665. SetEvent( hStateChangeEvent );
  666. //
  667. // If told to wait, block until scav thread signals the event
  668. //
  669. if (Flags & NOTIFY_FLAG_SYNCHRONOUS)
  670. {
  671. WaitForSingleObjectEx( hEvent,
  672. INFINITE,
  673. FALSE );
  674. CloseHandle( hEvent );
  675. }
  676. return( TRUE );
  677. }
  678. return( FALSE );
  679. }
  680. //+---------------------------------------------------------------------------
  681. //
  682. // Function: LsapInitializeScavenger
  683. //
  684. // Synopsis: Initialize Scavenger,
  685. //
  686. // Arguments: (none)
  687. //
  688. // History: 5-26-97 RichardW Created
  689. //
  690. // Notes:
  691. //
  692. //----------------------------------------------------------------------------
  693. BOOL
  694. LsapInitializeScavenger(
  695. VOID
  696. )
  697. {
  698. ULONG i ;
  699. PVOID hNotify ;
  700. HANDLE hThread ;
  701. DWORD tid ;
  702. DWORD Debugger ;
  703. DWORD dwSize ;
  704. DWORD dwType ;
  705. SYSTEM_KERNEL_DEBUGGER_INFORMATION KdInfo ;
  706. //
  707. // Initialize the lists
  708. //
  709. InitializeListHead( &NotifyList );
  710. InitializeListHead( &NotifyEvents );
  711. InitializeListHead( &ScavList );
  712. RtlInitializeCriticalSection( &ScavLock );
  713. RtlInitializeCriticalSection( &NotifyLock );
  714. //
  715. // Event set whenever there is a notification.
  716. //
  717. hStateChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  718. //
  719. // Create basic entries
  720. //
  721. hNotify = LsaIRegisterNotification( LsapScavengerHandleNotify,
  722. 0,
  723. NOTIFIER_TYPE_HANDLE_WAIT,
  724. 0,
  725. NOTIFIER_FLAG_NEW_THREAD,
  726. 0,
  727. hStateChangeEvent );
  728. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  729. TEXT("System\\CurrentControlSet\\Control\\Lsa"),
  730. 0,
  731. KEY_READ,
  732. &LsaRegistryKey ) == 0 )
  733. {
  734. LsaRegistryWatchEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  735. if ( LsaRegistryWatchEvent )
  736. {
  737. hNotify = LsaIRegisterNotification(
  738. LsapRegistryWatch,
  739. NULL,
  740. NOTIFIER_TYPE_HANDLE_WAIT,
  741. 0,
  742. NOTIFIER_FLAG_NEW_THREAD,
  743. 0,
  744. LsaRegistryWatchEvent );
  745. if ( hNotify )
  746. {
  747. //
  748. // Call it once to start the registry watch
  749. //
  750. LsapRegistryWatch( NULL );
  751. }
  752. else
  753. {
  754. CloseHandle( LsaRegistryWatchEvent );
  755. }
  756. }
  757. else
  758. {
  759. RegCloseKey( LsaRegistryKey );
  760. }
  761. }
  762. //
  763. // If we are under a debugger, or a kernel debugger is attached, or the
  764. // flag is in the registry, turn on the watch thread
  765. //
  766. Debugger = 0 ;
  767. dwSize = sizeof( Debugger );
  768. RegQueryValueEx( LsaRegistryKey,
  769. TEXT("EnableDebugCheck"),
  770. 0,
  771. &dwType,
  772. (PBYTE) &Debugger,
  773. &dwSize );
  774. NtQuerySystemInformation(
  775. SystemKernelDebuggerInformation,
  776. &KdInfo,
  777. sizeof( KdInfo ),
  778. NULL );
  779. if ( (KdInfo.KernelDebuggerEnabled) ||
  780. (NtCurrentPeb()->BeingDebugged) ||
  781. (Debugger != 0 ) )
  782. {
  783. LsapDebuggerOk = TRUE ;
  784. (void) LsaIRegisterNotification(
  785. LsapScavengerBreak,
  786. NULL,
  787. NOTIFIER_TYPE_INTERVAL,
  788. 0, // no class
  789. SCAV_INTERNAL_NO_TRACE, // no flags
  790. 60, // every minute
  791. NULL // no handle
  792. );
  793. }
  794. return TRUE ;
  795. }