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.

595 lines
16 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // ServiceMgr.cpp
  7. //
  8. // Description:
  9. // Service Manager implementation.
  10. //
  11. // Documentation:
  12. // Yes.
  13. //
  14. // Maintained By:
  15. // Galen Barbee (GalenB) 22-NOV-1999
  16. //
  17. //////////////////////////////////////////////////////////////////////////////
  18. #include "pch.h"
  19. // #include "ServiceMgr.h" - already included in DLL.H
  20. DEFINE_THISCLASS("CServiceManager")
  21. #define CServiceManager CServiceManager
  22. #define LPTHISCLASS CServiceManager *
  23. //****************************************************************************
  24. //
  25. // Protected Global
  26. //
  27. //****************************************************************************
  28. IServiceProvider * g_pspServiceManager = NULL;
  29. //****************************************************************************
  30. //
  31. // Class Static Variables
  32. //
  33. //****************************************************************************
  34. CRITICAL_SECTION * CServiceManager::sm_pcs = NULL;
  35. BOOL CServiceManager::sm_fShutDown = FALSE;
  36. //****************************************************************************
  37. //
  38. // Constructor / Destructor
  39. //
  40. //****************************************************************************
  41. //////////////////////////////////////////////////////////////////////////////
  42. //
  43. // HRESULT
  44. // CServiceManager::S_HrCreateInstance(
  45. // IUnknown ** ppunkOut
  46. // )
  47. //
  48. //////////////////////////////////////////////////////////////////////////////
  49. HRESULT
  50. CServiceManager::S_HrCreateInstance(
  51. IUnknown ** ppunkOut
  52. )
  53. {
  54. TraceFunc( "" );
  55. Assert( ppunkOut != NULL );
  56. HRESULT hr;
  57. LPUNKNOWN punk = NULL;
  58. //
  59. // Create a critical section to prevent lines from being fragmented.
  60. //
  61. if ( CServiceManager::sm_pcs == NULL )
  62. {
  63. PCRITICAL_SECTION pNewCritSect =
  64. (PCRITICAL_SECTION) HeapAlloc( GetProcessHeap(), 0, sizeof( CRITICAL_SECTION ) );
  65. if ( pNewCritSect == NULL )
  66. {
  67. hr = E_OUTOFMEMORY;
  68. goto Cleanup;
  69. } // if: creation failed
  70. InitializeCriticalSection( pNewCritSect );
  71. // Make sure we only have one log critical section
  72. InterlockedCompareExchangePointer( (PVOID *) &CServiceManager::sm_pcs, pNewCritSect, 0 );
  73. if ( CServiceManager::sm_pcs != pNewCritSect )
  74. {
  75. DeleteCriticalSection( pNewCritSect );
  76. HeapFree( GetProcessHeap(), 0, pNewCritSect );
  77. } // if: already have another critical section
  78. } // if: no critical section created yet
  79. Assert( CServiceManager::sm_pcs != NULL );
  80. EnterCriticalSection( CServiceManager::sm_pcs );
  81. if ( g_pspServiceManager != NULL )
  82. {
  83. hr = THR( g_pspServiceManager->TypeSafeQI( IUnknown, ppunkOut ) );
  84. } // if: assign new service manager
  85. else
  86. {
  87. LPTHISCLASS pthis = new CServiceManager( );
  88. if ( pthis != NULL )
  89. {
  90. //
  91. // Can't hold CS in Init.
  92. //
  93. LeaveCriticalSection( CServiceManager::sm_pcs );
  94. hr = THR( pthis->Init( ) );
  95. if ( SUCCEEDED( hr ) )
  96. {
  97. EnterCriticalSection( CServiceManager::sm_pcs );
  98. if ( g_pspServiceManager == NULL )
  99. {
  100. // No REF - or we'll never die!
  101. g_pspServiceManager = static_cast< IServiceProvider * >( pthis );
  102. TraceMoveToMemoryList( g_pspServiceManager, g_GlobalMemoryList );
  103. }
  104. if ( SUCCEEDED( hr ) )
  105. {
  106. hr = THR( g_pspServiceManager->TypeSafeQI( IUnknown, ppunkOut ) );
  107. }
  108. } // if: its our pointer
  109. } // if: got object
  110. pthis->Release( );
  111. } // else: create new one
  112. LeaveCriticalSection( CServiceManager::sm_pcs );
  113. Cleanup:
  114. HRETURN( hr );
  115. } //*** CServiceManager::S_HrCreateInstance( )
  116. //////////////////////////////////////////////////////////////////////////////
  117. //
  118. // CServiceManager::CServiceManager( void )
  119. //
  120. //////////////////////////////////////////////////////////////////////////////
  121. CServiceManager::CServiceManager( void )
  122. {
  123. TraceFunc( "" );
  124. InterlockedIncrement( &g_cObjects );
  125. TraceFuncExit();
  126. } //*** CServiceManager::CServiceManager( )
  127. //////////////////////////////////////////////////////////////////////////////
  128. //
  129. // STDMETHODIMP
  130. // CServiceManager::Init( void )
  131. //
  132. //////////////////////////////////////////////////////////////////////////////
  133. STDMETHODIMP
  134. CServiceManager::Init( void )
  135. {
  136. TraceFunc( "" );
  137. HRESULT hr;
  138. ITaskManager * ptm = NULL;
  139. IDoTask * pdt = NULL;
  140. IObjectManager * pom = NULL;
  141. INotificationManager * pnm = NULL;
  142. IConnectionManager * pcm = NULL;
  143. ILogManager * plm = NULL;
  144. // IUnknown stuff
  145. Assert( m_cRef == 0 );
  146. AddRef( );
  147. // IServiceProvider
  148. Assert( m_dwLogManagerCookie == 0 );
  149. Assert( m_dwConnectionManagerCookie == 0 );
  150. Assert( m_dwNotificationManagerCookie == 0 );
  151. Assert( m_dwObjectManagerCookie == 0 );
  152. Assert( m_dwTaskManagerCookie == 0 );
  153. Assert( m_pgit == NULL );
  154. // IServiceProvider stuff
  155. hr = THR( HrCoCreateInternalInstance( CLSID_ObjectManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( IObjectManager, &pom ) ) );
  156. if ( FAILED( hr ) )
  157. goto Cleanup;
  158. hr = THR( HrCoCreateInternalInstance( CLSID_TaskManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( ITaskManager, &ptm ) ) );
  159. if ( FAILED( hr ) )
  160. goto Cleanup;
  161. hr = THR( HrCoCreateInternalInstance( CLSID_NotificationManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( INotificationManager, &pnm ) ) );
  162. if ( FAILED( hr ) )
  163. goto Cleanup;
  164. hr = THR( HrCoCreateInternalInstance( CLSID_ClusterConnectionManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( IConnectionManager, &pcm ) ) );
  165. if ( FAILED( hr ) )
  166. goto Cleanup;
  167. hr = THR( HrCoCreateInternalInstance( CLSID_LogManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( ILogManager, &plm ) ) );
  168. if ( FAILED( hr ) )
  169. goto Cleanup;
  170. //
  171. // Store the interfaces in the GIT.
  172. //
  173. hr = THR( CoCreateInstance(
  174. CLSID_StdGlobalInterfaceTable
  175. , NULL
  176. , CLSCTX_INPROC_SERVER
  177. , IID_IGlobalInterfaceTable
  178. , reinterpret_cast< void ** >( &m_pgit )
  179. ) );
  180. if ( FAILED( hr ) )
  181. goto Cleanup;
  182. hr = THR( m_pgit->RegisterInterfaceInGlobal( pom, IID_IObjectManager, &m_dwObjectManagerCookie ) );
  183. if ( FAILED( hr ) )
  184. goto Cleanup;
  185. hr = THR( m_pgit->RegisterInterfaceInGlobal( ptm, IID_ITaskManager, &m_dwTaskManagerCookie ) );
  186. if ( FAILED( hr ) )
  187. goto Cleanup;
  188. hr = THR( m_pgit->RegisterInterfaceInGlobal( pnm, IID_INotificationManager, &m_dwNotificationManagerCookie ) );
  189. if ( FAILED( hr ) )
  190. goto Cleanup;
  191. hr = THR( m_pgit->RegisterInterfaceInGlobal( pcm, IID_IConnectionManager, &m_dwConnectionManagerCookie ) );
  192. if ( FAILED( hr ) )
  193. goto Cleanup;
  194. hr = THR( m_pgit->RegisterInterfaceInGlobal( plm, IID_ILogManager, &m_dwLogManagerCookie ) );
  195. if ( FAILED( hr ) )
  196. goto Cleanup;
  197. Cleanup:
  198. if ( pom != NULL )
  199. {
  200. pom->Release( );
  201. }
  202. if ( pnm != NULL )
  203. {
  204. pnm->Release( );
  205. }
  206. if ( pcm != NULL )
  207. {
  208. pcm->Release( );
  209. }
  210. if ( plm != NULL )
  211. {
  212. plm->Release( );
  213. }
  214. if ( ptm != NULL )
  215. {
  216. ptm->Release( );
  217. }
  218. if ( pdt != NULL )
  219. {
  220. pdt->Release( );
  221. }
  222. HRETURN( hr );
  223. } //*** CServiceManager::Init( )
  224. //////////////////////////////////////////////////////////////////////////////
  225. //
  226. // CServiceManager::~CServiceManager( void )
  227. //
  228. //////////////////////////////////////////////////////////////////////////////
  229. CServiceManager::~CServiceManager( void )
  230. {
  231. TraceFunc( "" );
  232. //HRESULT hr;
  233. //ITaskManager * ptm = NULL;
  234. //IDoTask * pdt = NULL;
  235. //IObjectManager * pom = NULL;
  236. //INotificationManager * pnm = NULL;
  237. //IConnectionManager * pcm = NULL;
  238. //ILogManager * plm = NULL;
  239. //
  240. // Indicate that we are shutting down.
  241. //
  242. sm_fShutDown = TRUE;
  243. EnterCriticalSection( CServiceManager::sm_pcs );
  244. if ( g_pspServiceManager == static_cast< IServiceProvider * >( this ) )
  245. {
  246. TraceMoveFromMemoryList( g_pspServiceManager, g_GlobalMemoryList );
  247. g_pspServiceManager = NULL;
  248. } // if: its our pointer
  249. if ( m_pgit != NULL )
  250. {
  251. if ( m_dwLogManagerCookie != 0 )
  252. {
  253. THR( m_pgit->RevokeInterfaceFromGlobal( m_dwLogManagerCookie ) );
  254. }
  255. if ( m_dwConnectionManagerCookie != 0 )
  256. {
  257. THR( m_pgit->RevokeInterfaceFromGlobal( m_dwConnectionManagerCookie ) );
  258. }
  259. if ( m_dwNotificationManagerCookie != 0 )
  260. {
  261. THR( m_pgit->RevokeInterfaceFromGlobal( m_dwNotificationManagerCookie ) );
  262. }
  263. if ( m_dwObjectManagerCookie != 0 )
  264. {
  265. THR( m_pgit->RevokeInterfaceFromGlobal( m_dwObjectManagerCookie ) );
  266. }
  267. if ( m_dwTaskManagerCookie != 0 )
  268. {
  269. THR( m_pgit->RevokeInterfaceFromGlobal( m_dwTaskManagerCookie ) );
  270. }
  271. m_pgit->Release( );
  272. }
  273. LeaveCriticalSection( CServiceManager::sm_pcs );
  274. //
  275. // TODO: gpease 01-AUG-2000
  276. // Figure out a way to free the CS.
  277. //
  278. InterlockedDecrement( &g_cObjects );
  279. TraceFuncExit();
  280. } //*** CServiceManager::~CServiceManager( )
  281. //****************************************************************************
  282. //
  283. // IUnknown
  284. //
  285. //****************************************************************************
  286. //////////////////////////////////////////////////////////////////////////////
  287. //
  288. // STDMETHODIMP
  289. // CServiceManager::QueryInterface(
  290. // REFIID riidIn,
  291. // LPVOID *ppvOut
  292. // )
  293. //
  294. //////////////////////////////////////////////////////////////////////////////
  295. STDMETHODIMP
  296. CServiceManager::QueryInterface(
  297. REFIID riidIn,
  298. LPVOID *ppvOut
  299. )
  300. {
  301. TraceQIFunc( riidIn, ppvOut );
  302. HRESULT hr = E_NOINTERFACE;
  303. if ( IsEqualIID( riidIn, IID_IUnknown ) )
  304. {
  305. *ppvOut = static_cast< LPUNKNOWN >( this );
  306. hr = S_OK;
  307. } // if: IUnknown
  308. else if ( IsEqualIID( riidIn, IID_IServiceProvider ) )
  309. {
  310. *ppvOut = TraceInterface( __THISCLASS__, IServiceProvider, this, 0 );
  311. hr = S_OK;
  312. } // else if: IQueryService
  313. if ( SUCCEEDED( hr ) )
  314. {
  315. ((IUnknown*) *ppvOut)->AddRef( );
  316. } // if: success
  317. QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
  318. } //*** CServiceManager::QueryInterface( )
  319. //////////////////////////////////////////////////////////////////////////////
  320. //
  321. // STDMETHODIMP_( ULONG )
  322. // CServiceManager::AddRef( void )
  323. //
  324. //////////////////////////////////////////////////////////////////////////////
  325. STDMETHODIMP_( ULONG )
  326. CServiceManager::AddRef( void )
  327. {
  328. TraceFunc( "[IUnknown]" );
  329. InterlockedIncrement( &m_cRef );
  330. RETURN( m_cRef );
  331. } //*** CServiceManager::AddRef( )
  332. //////////////////////////////////////////////////////////////////////////////
  333. //++
  334. //
  335. // STDMETHODIMP_( ULONG )
  336. // CServiceManager::Release( void )
  337. //
  338. //--
  339. //////////////////////////////////////////////////////////////////////////////
  340. STDMETHODIMP_( ULONG )
  341. CServiceManager::Release( void )
  342. {
  343. TraceFunc( "[IUnknown]" );
  344. LONG cRef;
  345. InterlockedDecrement( &m_cRef );
  346. cRef = m_cRef;
  347. if ( cRef == 0 )
  348. {
  349. TraceDo( delete this );
  350. }
  351. RETURN( cRef );
  352. } //*** CServiceManager::Release( )
  353. //****************************************************************************
  354. //
  355. // IServiceProvider
  356. //
  357. //****************************************************************************
  358. //////////////////////////////////////////////////////////////////////////////
  359. //++
  360. //
  361. // STDMETHODIMP
  362. // CServiceManager::QueryService(
  363. // REFCLSID rclsidIn,
  364. // REFIID riidInIn,
  365. // void ** ppvOutOut
  366. // )
  367. //
  368. //--
  369. //////////////////////////////////////////////////////////////////////////////
  370. STDMETHODIMP
  371. CServiceManager::QueryService(
  372. REFCLSID rclsidIn,
  373. REFIID riidInIn,
  374. void ** ppvOutOut
  375. )
  376. {
  377. TraceFunc( "[IServiceProvider]" );
  378. HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
  379. if ( m_pgit != NULL )
  380. {
  381. if ( IsEqualIID( rclsidIn, CLSID_ObjectManager ) )
  382. {
  383. IObjectManager * pom;
  384. hr = THR( m_pgit->GetInterfaceFromGlobal( m_dwObjectManagerCookie, TypeSafeParams( IObjectManager, &pom ) ) );
  385. if ( FAILED( hr ) )
  386. goto Cleanup;
  387. hr = THR( pom->QueryInterface( riidInIn, ppvOutOut ) );
  388. pom->Release( );
  389. // fall thru
  390. }
  391. else if ( IsEqualIID( rclsidIn, CLSID_TaskManager ) )
  392. {
  393. ITaskManager * ptm;
  394. hr = THR( m_pgit->GetInterfaceFromGlobal( m_dwTaskManagerCookie, TypeSafeParams( ITaskManager, &ptm ) ) );
  395. if ( FAILED( hr ) )
  396. goto Cleanup;
  397. hr = THR( ptm->QueryInterface( riidInIn, ppvOutOut ) );
  398. ptm->Release( );
  399. // fall thru
  400. }
  401. else if ( IsEqualIID( rclsidIn, CLSID_NotificationManager ) )
  402. {
  403. INotificationManager * pnm;
  404. hr = THR( m_pgit->GetInterfaceFromGlobal( m_dwNotificationManagerCookie, TypeSafeParams( INotificationManager, &pnm ) ) );
  405. if ( FAILED( hr ) )
  406. goto Cleanup;
  407. hr = THR( pnm->QueryInterface( riidInIn, ppvOutOut ) );
  408. pnm->Release( );
  409. // fall thru
  410. }
  411. else if ( IsEqualIID( rclsidIn, CLSID_ClusterConnectionManager ) )
  412. {
  413. IConnectionManager * pcm;
  414. hr = THR( m_pgit->GetInterfaceFromGlobal( m_dwConnectionManagerCookie, TypeSafeParams( IConnectionManager, &pcm ) ) );
  415. if ( FAILED( hr ) )
  416. goto Cleanup;
  417. hr = THR( pcm->QueryInterface( riidInIn, ppvOutOut ) );
  418. pcm->Release( );
  419. // fall thru
  420. }
  421. else if ( IsEqualIID( rclsidIn, CLSID_LogManager ) )
  422. {
  423. ILogManager * plm;
  424. hr = THR( m_pgit->GetInterfaceFromGlobal( m_dwLogManagerCookie, TypeSafeParams( ILogManager, &plm ) ) );
  425. if ( FAILED( hr ) )
  426. goto Cleanup;
  427. hr = THR( plm->QueryInterface( riidInIn, ppvOutOut ) );
  428. plm->Release( );
  429. // fall thru
  430. }
  431. }
  432. Cleanup:
  433. HRETURN( hr );
  434. } //*** CServiceManager::QueryService( )
  435. //****************************************************************************
  436. //
  437. // Private Methods
  438. //
  439. //****************************************************************************
  440. //////////////////////////////////////////////////////////////////////////////
  441. //++
  442. //
  443. // HRESULT
  444. // CServiceManager::S_HrGetManagerPointer(
  445. // IServiceProvider ** ppspOut
  446. // )
  447. //
  448. //--
  449. //////////////////////////////////////////////////////////////////////////////
  450. HRESULT
  451. CServiceManager::S_HrGetManagerPointer(
  452. IServiceProvider ** ppspOut
  453. )
  454. {
  455. TraceFunc( "ppspOut" );
  456. HRESULT hr = HRESULT_FROM_WIN32( ERROR_PROCESS_ABORTED );
  457. if ( CServiceManager::sm_fShutDown == FALSE )
  458. {
  459. EnterCriticalSection( CServiceManager::sm_pcs );
  460. if ( g_pspServiceManager != NULL )
  461. {
  462. *ppspOut = TraceInterface( __THISCLASS__,
  463. IServiceProvider,
  464. g_pspServiceManager,
  465. 0
  466. );
  467. (*ppspOut)->AddRef( );
  468. hr = S_OK;
  469. } // if: valid service manager
  470. else
  471. {
  472. hr = E_POINTER;
  473. } // else: no pointer
  474. LeaveCriticalSection( CServiceManager::sm_pcs );
  475. } // if: still up
  476. HRETURN ( hr );
  477. } //*** CServiceManager::S_HrGetManagerPointer( )