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.

591 lines
12 KiB

  1. //=================================================================
  2. //
  3. // PowerManagement.cpp --
  4. //
  5. // Copyright 1999- 2002 Microsoft Corporation
  6. //
  7. //=================================================================
  8. #include "precomp.h"
  9. #include <ntddip.h>
  10. #include <ntddtcp.h>
  11. #include "CIpRouteEvent.h"
  12. #include <provexpt.h>
  13. LONG CIPRouteEventProviderClassFactory::s_ObjectsInProgress = 0 ;
  14. LONG CIPRouteEventProviderClassFactory::s_LocksInProgress = 0 ;
  15. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  16. Class: CIPRouteEventProviderClassFactory
  17. Description: Provides class factory support for power management events
  18. Derivations: public IClassFactory
  19. Caveats:
  20. Raid:
  21. History: a-peterc 31-Mar-1999 Created
  22. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  23. //
  24. CIPRouteEventProviderClassFactory :: CIPRouteEventProviderClassFactory () : m_ReferenceCount ( 0 )
  25. {
  26. InterlockedIncrement ( &s_ObjectsInProgress ) ;
  27. }
  28. //
  29. CIPRouteEventProviderClassFactory::~CIPRouteEventProviderClassFactory ()
  30. {
  31. InterlockedDecrement ( &s_ObjectsInProgress ) ;
  32. }
  33. //
  34. STDMETHODIMP_( ULONG ) CIPRouteEventProviderClassFactory::AddRef()
  35. {
  36. return InterlockedIncrement ( &m_ReferenceCount ) ;
  37. }
  38. //
  39. STDMETHODIMP_(ULONG) CIPRouteEventProviderClassFactory::Release()
  40. {
  41. LONG ref ;
  42. if ( ( ref = InterlockedDecrement( &m_ReferenceCount ) ) == 0 )
  43. {
  44. delete this ;
  45. return 0 ;
  46. }
  47. else
  48. {
  49. return ref ;
  50. }
  51. }
  52. //
  53. BOOL CIPRouteEventProviderClassFactory::DllCanUnloadNow()
  54. {
  55. return ( !(s_ObjectsInProgress || s_LocksInProgress) ) ;
  56. }
  57. //***************************************************************************
  58. //
  59. // CBaseClassFactory::LockServer
  60. //
  61. // Purpose:
  62. // Increments or decrements the lock count of the DLL. If the
  63. // lock count goes to zero and there are no objects, the DLL
  64. // is allowed to unload. See DllCanUnloadNow.
  65. //
  66. // Parameters:
  67. // fLock BOOL specifying whether to increment or
  68. // decrement the lock count.
  69. //
  70. // Return Value:
  71. // HRESULT NOERROR always.
  72. //***************************************************************************
  73. STDMETHODIMP CIPRouteEventProviderClassFactory::LockServer ( BOOL a_fLock )
  74. {
  75. if ( a_fLock )
  76. {
  77. InterlockedIncrement ( &s_LocksInProgress ) ;
  78. }
  79. else
  80. {
  81. InterlockedDecrement ( &s_LocksInProgress ) ;
  82. }
  83. return S_OK ;
  84. }
  85. //
  86. STDMETHODIMP CIPRouteEventProviderClassFactory::QueryInterface (
  87. REFIID a_riid,
  88. PPVOID a_ppv
  89. )
  90. {
  91. *a_ppv = NULL ;
  92. if ( IID_IUnknown == a_riid || IID_IClassFactory == a_riid )
  93. {
  94. *a_ppv = this ;
  95. }
  96. if ( NULL != *a_ppv )
  97. {
  98. AddRef() ;
  99. return NOERROR ;
  100. }
  101. return ResultFromScode( E_NOINTERFACE ) ;
  102. }
  103. //***************************************************************************
  104. //
  105. // CIPRouteEventProviderClassFactory::CreateInstance
  106. //
  107. // Purpose: Instantiates a Event Provider object returning an interface pointer.
  108. //
  109. // Parameters:
  110. // pUnkOuter LPUNKNOWN to the controlling IUnknown if we are
  111. // being used in an aggregation.
  112. // riid REFIID identifying the interface the caller
  113. // desires to have for the new object.
  114. // ppvObj PPVOID in which to store the desired
  115. // interface pointer for the new object.
  116. //
  117. // Return Value:
  118. // HRESULT NOERROR if successful, otherwise E_NOINTERFACE
  119. // if we cannot support the requested interface.
  120. //***************************************************************************
  121. STDMETHODIMP CIPRouteEventProviderClassFactory :: CreateInstance (
  122. LPUNKNOWN a_pUnkOuter ,
  123. REFIID a_riid ,
  124. LPVOID FAR *a_ppvObject
  125. )
  126. {
  127. HRESULT t_status = S_OK ;
  128. if ( a_pUnkOuter )
  129. {
  130. t_status = CLASS_E_NOAGGREGATION ;
  131. }
  132. else
  133. {
  134. try
  135. {
  136. //
  137. // new throws Heap_Exception exception
  138. //
  139. IWbemProviderInit *t_lpunk = ( IWbemProviderInit * ) new CIPRouteEventProvider ;
  140. if ( t_lpunk == NULL )
  141. {
  142. t_status = E_OUTOFMEMORY;
  143. }
  144. else
  145. {
  146. t_status = t_lpunk->QueryInterface ( a_riid , a_ppvObject ) ;
  147. if ( FAILED ( t_status ) )
  148. {
  149. delete t_lpunk ;
  150. }
  151. }
  152. }
  153. catch ( Heap_Exception& e_HE )
  154. {
  155. t_status = E_OUTOFMEMORY ;
  156. }
  157. }
  158. return t_status ;
  159. }
  160. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  161. Class: CIPRouteEventProvider
  162. Description: Provider support for power management events
  163. Derivations: public CIPRouteEventProvider,
  164. public IWbemEventProvider,
  165. public IWbemProviderInit
  166. Caveats:
  167. Raid:
  168. History: a-peterc 31-Mar-1999 Created
  169. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  170. // Event provider object
  171. CIPRouteEventProvider :: CIPRouteEventProvider () : m_ReferenceCount( 0 ) ,
  172. m_pHandler(NULL),
  173. m_pClass(NULL),
  174. m_dwThreadID(NULL)
  175. {
  176. InterlockedIncrement ( &CIPRouteEventProviderClassFactory::s_ObjectsInProgress ) ;
  177. InitializeCriticalSection ( &m_csEvent ) ;
  178. // Create a thread that will spin off an event loop
  179. NTSTATUS t_NtStatus = NtCreateEvent (
  180. &m_TerminationEventHandle,
  181. EVENT_ALL_ACCESS,
  182. NULL,
  183. SynchronizationEvent,
  184. FALSE
  185. ) ;
  186. if (NT_SUCCESS(t_NtStatus))
  187. {
  188. m_hThreadHandle = CreateThread (
  189. NULL, // pointer to security attributes
  190. 0L, // initial thread stack size
  191. dwThreadProc, // pointer to thread function
  192. this, // argument for new thread
  193. 0L, // creation flags
  194. &m_dwThreadID
  195. ) ;
  196. }
  197. }
  198. //
  199. CIPRouteEventProvider :: ~CIPRouteEventProvider ()
  200. {
  201. LONG t_PreviousState = 0 ;
  202. if ( (m_hThreadHandle != INVALID_HANDLE_VALUE) && (m_TerminationEventHandle != INVALID_HANDLE_VALUE) )
  203. {
  204. //the worker thread should exit...
  205. NTSTATUS t_NtStatus = NtSetEvent (
  206. m_TerminationEventHandle ,
  207. & t_PreviousState
  208. ) ;
  209. if (!NT_SUCCESS(t_NtStatus))
  210. {
  211. //fallback - next wait will fail and the thread should exit.
  212. m_TerminationEventHandle = INVALID_HANDLE_VALUE;
  213. }
  214. t_NtStatus = NtWaitForSingleObject ( m_hThreadHandle , FALSE, NULL ) ;
  215. }
  216. DeleteCriticalSection ( &m_csEvent ) ;
  217. if ( m_pHandler )
  218. {
  219. m_pHandler->Release () ;
  220. m_pHandler = NULL ;
  221. }
  222. if ( m_pClass )
  223. {
  224. m_pClass->Release () ;
  225. m_pClass = NULL ;
  226. }
  227. InterlockedDecrement ( & CIPRouteEventProviderClassFactory::s_ObjectsInProgress ) ;
  228. }
  229. //
  230. STDMETHODIMP_( ULONG ) CIPRouteEventProvider :: AddRef ()
  231. {
  232. return InterlockedIncrement ( &m_ReferenceCount ) ;
  233. }
  234. //
  235. STDMETHODIMP_(ULONG) CIPRouteEventProvider :: Release ()
  236. {
  237. LONG t_ref ;
  238. if ( ( t_ref = InterlockedDecrement ( &m_ReferenceCount ) ) == 0 )
  239. {
  240. delete this ;
  241. return 0 ;
  242. }
  243. else
  244. {
  245. return t_ref ;
  246. }
  247. }
  248. //
  249. STDMETHODIMP CIPRouteEventProvider :: QueryInterface (
  250. REFIID a_riid,
  251. void **a_ppv
  252. )
  253. {
  254. if ( NULL == a_ppv )
  255. {
  256. return E_INVALIDARG ;
  257. }
  258. else
  259. {
  260. *a_ppv = NULL ;
  261. }
  262. if( a_riid == IID_IWbemEventProvider )
  263. {
  264. *a_ppv = (IWbemEventProvider *)this ;
  265. }
  266. else if ( a_riid == IID_IWbemProviderInit )
  267. {
  268. *a_ppv = (IWbemProviderInit *) this ;
  269. }
  270. else if ( a_riid == IID_IUnknown )
  271. {
  272. *a_ppv = (IWbemProviderInit *) this ;
  273. }
  274. if (*a_ppv != NULL)
  275. {
  276. AddRef() ;
  277. return S_OK ;
  278. }
  279. else
  280. {
  281. return E_NOINTERFACE ;
  282. }
  283. }
  284. //
  285. STDMETHODIMP CIPRouteEventProvider::Initialize (
  286. LPWSTR a_wszUser,
  287. long a_lFlags,
  288. LPWSTR a_wszNamespace,
  289. LPWSTR a_wszLocale,
  290. IWbemServices *a_pNamespace,
  291. IWbemContext *a_pCtx,
  292. IWbemProviderInitSink *a_pSink
  293. )
  294. {
  295. HRESULT t_hRes = WBEM_E_OUT_OF_MEMORY;
  296. if ( (m_hThreadHandle != INVALID_HANDLE_VALUE) && (m_TerminationEventHandle != INVALID_HANDLE_VALUE) )
  297. {
  298. IWbemClassObject *t_pEventClass = NULL;
  299. BSTR t_bstrClass = SysAllocString (IPROUTE_EVENT_CLASS);
  300. if (t_bstrClass)
  301. {
  302. t_hRes = a_pNamespace->GetObject (
  303. t_bstrClass,
  304. 0,
  305. a_pCtx,
  306. &t_pEventClass,
  307. NULL
  308. ) ;
  309. // ptr initialization routines
  310. if (SUCCEEDED(t_hRes))
  311. {
  312. SetClass ( t_pEventClass ) ;
  313. }
  314. SysFreeString ( t_bstrClass ) ;
  315. }
  316. }
  317. else
  318. {
  319. t_hRes = WBEM_E_FAILED;
  320. }
  321. a_pSink->SetStatus( t_hRes, 0 ) ;
  322. return t_hRes ;
  323. }
  324. //
  325. STDMETHODIMP CIPRouteEventProvider::ProvideEvents (
  326. IWbemObjectSink *a_pSink,
  327. long a_lFlags
  328. )
  329. {
  330. SetHandler( a_pSink ) ;
  331. return S_OK ;
  332. }
  333. void CIPRouteEventProvider::SetHandler( IWbemObjectSink __RPC_FAR *a_pHandler )
  334. {
  335. EnterCriticalSection( &m_csEvent ) ;
  336. if ( m_pHandler )
  337. {
  338. m_pHandler->Release() ;
  339. }
  340. m_pHandler = a_pHandler ;
  341. if ( m_pHandler )
  342. {
  343. m_pHandler->AddRef() ;
  344. }
  345. LeaveCriticalSection( &m_csEvent ) ;
  346. }
  347. //
  348. void CIPRouteEventProvider::SetClass ( IWbemClassObject *a_pClass )
  349. {
  350. EnterCriticalSection( &m_csEvent ) ;
  351. if ( m_pClass )
  352. {
  353. m_pClass->Release() ;
  354. }
  355. m_pClass = a_pClass ;
  356. if ( m_pClass )
  357. {
  358. m_pClass->AddRef() ;
  359. }
  360. LeaveCriticalSection( &m_csEvent ) ;
  361. }
  362. // worker thread pump
  363. DWORD WINAPI CIPRouteEventProvider :: dwThreadProc ( LPVOID a_lpParameter )
  364. {
  365. CIPRouteEventProvider *t_pThis = ( CIPRouteEventProvider * ) a_lpParameter ;
  366. if ( t_pThis )
  367. {
  368. SmartCloseNtHandle t_StackHandle ;
  369. SmartCloseNtHandle t_CompleteEventHandle ;
  370. NTSTATUS t_NtStatus = t_pThis->OpenQuerySource (
  371. t_StackHandle ,
  372. t_CompleteEventHandle
  373. ) ;
  374. BOOL t_Continue = TRUE ;
  375. while ( t_Continue && NT_SUCCESS ( t_NtStatus ) )
  376. {
  377. IO_STATUS_BLOCK t_IoStatusBlock ;
  378. t_NtStatus = NtDeviceIoControlFile (
  379. t_StackHandle,
  380. (HANDLE) t_CompleteEventHandle ,
  381. (PIO_APC_ROUTINE) NULL,
  382. (PVOID) NULL,
  383. &t_IoStatusBlock,
  384. IOCTL_IP_RTCHANGE_NOTIFY_REQUEST,
  385. NULL, // input buffer
  386. 0,
  387. NULL , // output buffer
  388. 0
  389. ) ;
  390. if ( t_NtStatus == STATUS_PENDING )
  391. {
  392. HANDLE t_WaitArray [ 2 ] ;
  393. t_WaitArray [ 0 ] = (HANDLE)t_CompleteEventHandle ;
  394. t_WaitArray [ 1 ] = (HANDLE)t_pThis->m_TerminationEventHandle ;
  395. t_NtStatus = NtWaitForMultipleObjects (
  396. 2 ,
  397. t_WaitArray ,
  398. WaitAny,
  399. FALSE ,
  400. NULL
  401. );
  402. switch ( t_NtStatus )
  403. {
  404. case STATUS_WAIT_0:
  405. {
  406. }
  407. break ;
  408. case STATUS_WAIT_1:
  409. {
  410. t_Continue = FALSE ;
  411. }
  412. break ;
  413. default:
  414. {
  415. t_Continue = FALSE ;
  416. }
  417. break ;
  418. }
  419. }
  420. else if ( t_NtStatus != STATUS_SUCCESS )
  421. {
  422. }
  423. else if ( t_IoStatusBlock.Status != STATUS_SUCCESS )
  424. {
  425. }
  426. if ( NT_SUCCESS ( t_NtStatus ) )
  427. {
  428. t_pThis->SendEvent () ;
  429. }
  430. }
  431. }
  432. return 0 ;
  433. }
  434. void CIPRouteEventProvider::SendEvent ()
  435. {
  436. if( m_pClass && m_pHandler)
  437. {
  438. IWbemClassObject *t_pInst = NULL ;
  439. if( SUCCEEDED( m_pClass->SpawnInstance( 0L, &t_pInst ) ) )
  440. {
  441. m_pHandler->Indicate ( 1, &t_pInst ) ;
  442. }
  443. t_pInst->Release() ;
  444. }
  445. }
  446. NTSTATUS CIPRouteEventProvider::OpenQuerySource (
  447. HANDLE &a_StackHandle ,
  448. HANDLE &a_CompleteEventHandle
  449. )
  450. {
  451. UNICODE_STRING t_Stack ;
  452. RtlInitUnicodeString ( & t_Stack , DD_IP_DEVICE_NAME ) ;
  453. OBJECT_ATTRIBUTES t_Attributes;
  454. InitializeObjectAttributes (
  455. &t_Attributes,
  456. &t_Stack ,
  457. OBJ_CASE_INSENSITIVE,
  458. NULL,
  459. NULL
  460. ) ;
  461. IO_STATUS_BLOCK t_IoStatusBlock ;
  462. NTSTATUS t_NtStatus = NtOpenFile (
  463. &a_StackHandle,
  464. GENERIC_EXECUTE,
  465. &t_Attributes,
  466. &t_IoStatusBlock,
  467. FILE_SHARE_READ,
  468. 0
  469. );
  470. if ( NT_SUCCESS ( t_NtStatus ) )
  471. {
  472. t_NtStatus = NtCreateEvent (
  473. &a_CompleteEventHandle,
  474. EVENT_ALL_ACCESS,
  475. NULL,
  476. SynchronizationEvent,
  477. FALSE
  478. ) ;
  479. if ( ! NT_SUCCESS ( t_NtStatus ) )
  480. {
  481. NtClose ( a_StackHandle ) ;
  482. a_StackHandle = INVALID_HANDLE_VALUE ;
  483. }
  484. }
  485. return t_NtStatus ;
  486. }