Source code of Windows XP (NT5)
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.

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