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.

720 lines
19 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // TaskPollingCallback.cpp
  7. //
  8. // Description:
  9. // CTaskPollingCallback implementation.
  10. //
  11. // Maintained By:
  12. // Galen Barbee (GalenB) 10-JUL-2000
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. #include "Pch.h"
  16. #include <ClusCfgPrivate.h>
  17. #include "TaskPollingCallback.h"
  18. DEFINE_THISCLASS("CTaskPollingCallback")
  19. // ************************************************************************
  20. //
  21. // Constructor / Destructor
  22. //
  23. // ************************************************************************
  24. //////////////////////////////////////////////////////////////////////////////
  25. //++
  26. //
  27. // HRESULT
  28. // CTaskPollingCallback::S_HrCreateInstance(
  29. // IUnknown ** ppunkOut
  30. // )
  31. //
  32. //--
  33. //////////////////////////////////////////////////////////////////////////////
  34. HRESULT
  35. CTaskPollingCallback::S_HrCreateInstance(
  36. IUnknown ** ppunkOut
  37. )
  38. {
  39. TraceFunc( "" );
  40. HRESULT hr = S_OK;
  41. CTaskPollingCallback * ptpc = NULL;
  42. Assert( ppunkOut != NULL );
  43. if ( ppunkOut == NULL )
  44. {
  45. hr = THR( E_POINTER );
  46. goto Cleanup;
  47. } // if:
  48. ptpc = new CTaskPollingCallback;
  49. if ( ptpc == NULL )
  50. {
  51. hr = THR( E_OUTOFMEMORY );
  52. goto Cleanup;
  53. } // if:
  54. hr = THR( ptpc->HrInit() );
  55. if ( FAILED( hr ) )
  56. {
  57. goto Cleanup;
  58. } // if:
  59. hr = THR( ptpc->TypeSafeQI( IUnknown, ppunkOut ) );
  60. if ( FAILED( hr ) )
  61. {
  62. goto Cleanup;
  63. } // if:
  64. TraceMoveToMemoryList( *ppunkOut, g_GlobalMemoryList );
  65. Cleanup:
  66. if ( ptpc != NULL )
  67. {
  68. ptpc->Release();
  69. } // if:
  70. HRETURN( hr );
  71. } //*** CTaskPollingCallback::S_HrCreateInstance
  72. //////////////////////////////////////////////////////////////////////////////
  73. //++
  74. //
  75. // CTaskPollingCallback::CTaskPollingCallback
  76. //
  77. //--
  78. //////////////////////////////////////////////////////////////////////////////
  79. CTaskPollingCallback::CTaskPollingCallback( void )
  80. : m_cRef( 1 )
  81. {
  82. TraceFunc( "" );
  83. InterlockedIncrement( &g_cObjects );
  84. Assert( m_fStop == false );
  85. Assert( m_dwRemoteServerObjectGITCookie == 0 );
  86. Assert( m_cookieLocalServerObject == 0 );
  87. TraceFuncExit();
  88. } //*** CTaskPollingCallback::CTaskPollingCallback
  89. //////////////////////////////////////////////////////////////////////////////
  90. //++
  91. //
  92. // STDMETHODIMP
  93. // CTaskPollingCallback::HrInit
  94. //
  95. //--
  96. //////////////////////////////////////////////////////////////////////////////
  97. STDMETHODIMP
  98. CTaskPollingCallback::HrInit( void )
  99. {
  100. TraceFunc( "" );
  101. HRESULT hr = S_OK;
  102. // IUnknown
  103. Assert( m_cRef == 1 );
  104. HRETURN( hr );
  105. } //*** CTaskPollingCallback::HrInit
  106. //////////////////////////////////////////////////////////////////////////////
  107. //++
  108. //
  109. // CTaskPollingCallback::~CTaskPollingCallback
  110. //
  111. //--
  112. //////////////////////////////////////////////////////////////////////////////
  113. CTaskPollingCallback::~CTaskPollingCallback( void )
  114. {
  115. TraceFunc( "" );
  116. TraceMoveFromMemoryList( this, g_GlobalMemoryList );
  117. InterlockedDecrement( &g_cObjects );
  118. TraceFuncExit();
  119. } //*** CTaskPollingCallback::~CTaskPollingCallback
  120. // ************************************************************************
  121. //
  122. // IUnknown
  123. //
  124. // ************************************************************************
  125. //////////////////////////////////////////////////////////////////////////////
  126. //++
  127. //
  128. // CTaskPollingCallback::QueryInterface
  129. //
  130. // Description:
  131. // Query this object for the passed in interface.
  132. //
  133. // Arguments:
  134. // riidIn
  135. // Id of interface requested.
  136. //
  137. // ppvOut
  138. // Pointer to the requested interface.
  139. //
  140. // Return Value:
  141. // S_OK
  142. // If the interface is available on this object.
  143. //
  144. // E_NOINTERFACE
  145. // If the interface is not available.
  146. //
  147. // E_POINTER
  148. // ppvOut was NULL.
  149. //
  150. // Remarks:
  151. // None.
  152. //
  153. //--
  154. //////////////////////////////////////////////////////////////////////////////
  155. STDMETHODIMP
  156. CTaskPollingCallback::QueryInterface(
  157. REFIID riidIn
  158. , LPVOID * ppvOut
  159. )
  160. {
  161. TraceQIFunc( riidIn, ppvOut );
  162. HRESULT hr = S_OK;
  163. //
  164. // Validate arguments.
  165. //
  166. Assert( ppvOut != NULL );
  167. if ( ppvOut == NULL )
  168. {
  169. hr = THR( E_POINTER );
  170. goto Cleanup;
  171. } // if:
  172. //
  173. // Handle known interfaces.
  174. //
  175. if ( IsEqualIID( riidIn, IID_IUnknown ) )
  176. {
  177. *ppvOut = static_cast< ITaskPollingCallback * >( this );
  178. } // if: IUnknown
  179. else if ( IsEqualIID( riidIn, IID_ITaskPollingCallback ) )
  180. {
  181. *ppvOut = TraceInterface( __THISCLASS__, ITaskPollingCallback, this, 0 );
  182. } // else if: ITaskPollingCallback
  183. else if ( IsEqualIID( riidIn, IID_IDoTask ) )
  184. {
  185. *ppvOut = TraceInterface( __THISCLASS__, IDoTask, this, 0 );
  186. } // else if: IDoTask
  187. else
  188. {
  189. *ppvOut = NULL;
  190. hr = E_NOINTERFACE;
  191. } // else:
  192. //
  193. // Add a reference to the interface if successful.
  194. //
  195. if ( SUCCEEDED( hr ) )
  196. {
  197. ((IUnknown *) *ppvOut)->AddRef();
  198. } // if: success
  199. Cleanup:
  200. QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
  201. } //*** CTaskPollingCallback::QueryInterface
  202. //////////////////////////////////////////////////////////////////////////////
  203. //++
  204. //
  205. // STDMETHODIMP_( ULONG )
  206. // CTaskPollingCallback::AddRef
  207. //
  208. //--
  209. //////////////////////////////////////////////////////////////////////////////
  210. STDMETHODIMP_( ULONG )
  211. CTaskPollingCallback::AddRef( void )
  212. {
  213. TraceFunc( "[IUnknown]" );
  214. InterlockedIncrement( &m_cRef );
  215. CRETURN( m_cRef );
  216. } //*** CTaskPollingCallback::AddRef
  217. //////////////////////////////////////////////////////////////////////////////
  218. //++
  219. //
  220. // STDMETHODIMP_( ULONG )
  221. // CTaskPollingCallback::Release
  222. //
  223. //--
  224. //////////////////////////////////////////////////////////////////////////////
  225. STDMETHODIMP_( ULONG )
  226. CTaskPollingCallback::Release( void )
  227. {
  228. TraceFunc( "[IUnknown]" );
  229. LONG cRef;
  230. cRef = InterlockedDecrement( &m_cRef );
  231. if ( cRef == 0 )
  232. {
  233. TraceDo( delete this );
  234. } // if:
  235. CRETURN( cRef );
  236. } //*** CTaskPollingCallback::Release
  237. //****************************************************************************
  238. //
  239. // ITaskPollingCallback
  240. //
  241. //****************************************************************************
  242. //////////////////////////////////////////////////////////////////////////////
  243. //++
  244. //
  245. // STDMETHODIMP
  246. // CTaskPollingCallback::BeginTask( void )
  247. //
  248. //--
  249. //////////////////////////////////////////////////////////////////////////////
  250. STDMETHODIMP
  251. CTaskPollingCallback::BeginTask( void )
  252. {
  253. TraceFunc( "[IDoTask]" );
  254. HRESULT hr = S_OK;
  255. BSTR bstrNodeName = NULL;
  256. BSTR bstrLastNodeName = NULL;
  257. BSTR bstrReference = NULL;
  258. BSTR bstrDescription = NULL;
  259. BSTR bstrNodeConnectedTo = NULL;
  260. CLSID clsidTaskMajor;
  261. CLSID clsidTaskMinor;
  262. ULONG ulMin;
  263. ULONG ulMax;
  264. ULONG ulCurrent;
  265. HRESULT hrStatus;
  266. FILETIME ft;
  267. IGlobalInterfaceTable * pgit = NULL;
  268. IClusCfgServer * pccs = NULL;
  269. IClusCfgPollingCallback * piccpc = NULL;
  270. IClusCfgPollingCallbackInfo * piccpci = NULL;
  271. IServiceProvider * psp = NULL;
  272. IConnectionPointContainer * pcpc = NULL;
  273. IConnectionPoint * pcp = NULL;
  274. IClusCfgCallback * pcccb = NULL;
  275. DWORD cRetries = 0;
  276. IObjectManager * pom = NULL;
  277. //
  278. // Collect the manager we need to complete this task.
  279. //
  280. hr = THR( CoCreateInstance( CLSID_ServiceManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( IServiceProvider, &psp ) ) );
  281. if ( FAILED( hr ) )
  282. {
  283. goto Cleanup;
  284. } // if:
  285. hr = THR( psp->TypeSafeQS( CLSID_NotificationManager, IConnectionPointContainer, &pcpc ) );
  286. if ( FAILED( hr ) )
  287. {
  288. goto Cleanup;
  289. } // if:
  290. hr = THR( psp->TypeSafeQS( CLSID_ObjectManager, IObjectManager, &pom ) );
  291. if ( FAILED( hr ) )
  292. {
  293. goto Cleanup;
  294. } // if:
  295. hr = THR( pcpc->FindConnectionPoint( IID_IClusCfgCallback, &pcp ) );
  296. if ( FAILED( hr ) )
  297. {
  298. goto Cleanup;
  299. } // if:
  300. hr = THR( pcp->TypeSafeQI( IClusCfgCallback, &pcccb ) );
  301. if ( FAILED( hr ) )
  302. {
  303. goto Cleanup;
  304. } // if:
  305. psp->Release();
  306. psp = NULL;
  307. //
  308. // Create the GIT.
  309. //
  310. hr = THR( CoCreateInstance(
  311. CLSID_StdGlobalInterfaceTable
  312. , NULL
  313. , CLSCTX_INPROC_SERVER
  314. , IID_IGlobalInterfaceTable
  315. , reinterpret_cast< void ** >( &pgit )
  316. ) );
  317. if ( FAILED( hr ) )
  318. {
  319. goto Cleanup;
  320. } // if
  321. //
  322. // Get the ClusCfgServer interface from the GIT.
  323. //
  324. Assert( m_dwRemoteServerObjectGITCookie != 0 );
  325. hr = THR( pgit->GetInterfaceFromGlobal( m_dwRemoteServerObjectGITCookie, IID_IClusCfgServer, reinterpret_cast< void ** >( &pccs ) ) );
  326. if ( FAILED( hr ) )
  327. {
  328. goto Cleanup;
  329. } // if
  330. //
  331. // Get the PollingCallback object from the server.
  332. //
  333. hr = THR( pccs->TypeSafeQI( IClusCfgPollingCallbackInfo, &piccpci ) );
  334. if ( FAILED( hr ) )
  335. {
  336. goto Cleanup;
  337. } // if
  338. hr = THR( piccpci->GetCallback( &piccpc ) );
  339. if ( FAILED( hr ) )
  340. {
  341. goto Cleanup;
  342. } // if
  343. hr = THR( HrRetrieveCookiesName( pom, m_cookieLocalServerObject, &bstrNodeConnectedTo ) );
  344. if ( FAILED( hr ) )
  345. {
  346. goto Cleanup;
  347. } // if
  348. pom->Release();
  349. pom = NULL;
  350. //
  351. // Begin polling for SendStatusReports.
  352. //
  353. while ( m_fStop == FALSE )
  354. {
  355. //
  356. // When the we cannot get a service manager pointer then it's time to
  357. // leave...
  358. //
  359. // Don't wrap with THR because we are expecting an error.
  360. //
  361. hr = CServiceManager::S_HrGetManagerPointer( &psp );
  362. if ( FAILED( hr ) )
  363. {
  364. break;
  365. } // if:
  366. psp->Release();
  367. psp = NULL;
  368. if ( bstrNodeName != NULL )
  369. {
  370. TraceSysFreeString( bstrLastNodeName );
  371. bstrLastNodeName = NULL;
  372. //
  373. // Give up ownership
  374. //
  375. bstrLastNodeName = bstrNodeName;
  376. bstrNodeName = NULL;
  377. } // if:
  378. TraceSysFreeString( bstrDescription );
  379. bstrDescription = NULL;
  380. TraceSysFreeString( bstrReference );
  381. bstrReference = NULL;
  382. hr = STHR( piccpc->GetStatusReport(
  383. &bstrNodeName
  384. , &clsidTaskMajor
  385. , &clsidTaskMinor
  386. , &ulMin
  387. , &ulMax
  388. , &ulCurrent
  389. , &hrStatus
  390. , &bstrDescription
  391. , &ft
  392. , &bstrReference
  393. ) );
  394. if ( FAILED( hr ) )
  395. {
  396. HRESULT hr2;
  397. BSTR bstrNotification = NULL;
  398. BSTR bstrRef = NULL;
  399. LogMsg( L"[TaskPollingCallback] GetStatusReport() failed for node %ws. (hr = %#08x)", bstrNodeConnectedTo, hr );
  400. THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_POLLING_CONNECTION_FAILURE, &bstrNotification, bstrNodeConnectedTo ) );
  401. THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_POLLING_CONNECTION_FAILURE_REF, &bstrRef ) );
  402. //
  403. // Don't show this in the UI as a failure since it may succeed later and we don't want a
  404. // red X and a green status bar at the end.
  405. //
  406. hr2 = THR( pcccb->SendStatusReport(
  407. bstrLastNodeName
  408. , TASKID_Major_Establish_Connection
  409. , TASKID_Minor_Polling_Connection_Failure
  410. , 0
  411. , 1
  412. , 1
  413. , MAKE_HRESULT( SEVERITY_SUCCESS, HRESULT_FACILITY( hr ), HRESULT_CODE( hr ) )
  414. , bstrNotification
  415. , NULL
  416. , bstrRef
  417. ) );
  418. TraceSysFreeString( bstrNotification );
  419. TraceSysFreeString( bstrRef );
  420. if ( hr2 == E_ABORT )
  421. {
  422. LogMsg( L"[TaskPollingCallback] UI layer returned E_ABORT..." );
  423. } // if:
  424. //
  425. // If we had an error then sleep for a little more time before
  426. // trying again.
  427. //
  428. Sleep( TPC_WAIT_AFTER_FAILURE );
  429. //
  430. // Increment the retry count.
  431. //
  432. cRetries++;
  433. //
  434. // If we are exceeding our max retry count then it's time to leave
  435. // and notify the UI that we are have lost connection to the
  436. // server...
  437. //
  438. if ( cRetries >= TPC_MAX_RETRIES_ON_FAILURE )
  439. {
  440. BSTR bstrDesc = NULL;
  441. BSTR bstrTempRef = NULL;
  442. THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_DISCONNECTING_FROM_SERVER, &bstrDesc, bstrNodeConnectedTo ) );
  443. THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_DISCONNECTING_FROM_SERVER_REF, &bstrTempRef ) );
  444. LogMsg( L"[TaskPollingCallback] GetStatusReport() failed for node %ws too many times and has timed out. Aborting polling. (hr = %#08x)", bstrNodeConnectedTo, hr );
  445. THR( pcccb->SendStatusReport(
  446. bstrNodeConnectedTo
  447. , TASKID_Major_Find_Devices
  448. , TASKID_Minor_Disconnecting_From_Server
  449. , 1
  450. , 1
  451. , 1
  452. , hr
  453. , bstrDesc
  454. , NULL
  455. , bstrTempRef
  456. ) );
  457. TraceSysFreeString( bstrDesc );
  458. TraceSysFreeString( bstrTempRef );
  459. goto Cleanup;
  460. } // if:
  461. } // if: GetStatusReport() failed
  462. else if ( hr == S_OK )
  463. {
  464. HRESULT hrTmp;
  465. TraceMemoryAddBSTR( bstrNodeName );
  466. TraceMemoryAddBSTR( bstrDescription );
  467. TraceMemoryAddBSTR( bstrReference );
  468. hr = THR( pcccb->SendStatusReport(
  469. bstrNodeName
  470. , clsidTaskMajor
  471. , clsidTaskMinor
  472. , ulMin
  473. , ulMax
  474. , ulCurrent
  475. , hrStatus
  476. , bstrDescription
  477. , &ft
  478. , bstrReference
  479. ) );
  480. if ( hr == E_ABORT )
  481. {
  482. LogMsg( L"[TaskPollingCallback] UI layer returned E_ABORT and it is being sent to the server." );
  483. } // if:
  484. hrTmp = hr;
  485. hr = THR( piccpc->SetHResult( hrTmp ) );
  486. if ( FAILED( hr ) )
  487. {
  488. LogMsg( L"[TaskPollingCallback] SetHResult() failed. hr = 0x%08x", hr );
  489. } // if:
  490. //
  491. // Need to reset the retry count when we successfully round trip a status report.
  492. //
  493. cRetries = 0;
  494. } // else if: GetStatusReport() retrieved an item
  495. else
  496. {
  497. //
  498. // Need to reset the retry count when we successfully round trip a status report.
  499. //
  500. cRetries = 0;
  501. Sleep( TPC_POLL_INTERVAL );
  502. } // else: GetStatusReport() didn't find and item waiting
  503. } // while:
  504. Cleanup:
  505. if ( pom != NULL )
  506. {
  507. pom->Release();
  508. } // if:
  509. if ( psp != NULL )
  510. {
  511. psp->Release();
  512. } // if:
  513. if ( pgit != NULL )
  514. {
  515. pgit->Release();
  516. } // if:
  517. if ( pccs != NULL )
  518. {
  519. pccs->Release();
  520. } // if:
  521. if ( piccpc != NULL )
  522. {
  523. piccpc->Release();
  524. } // if:
  525. if ( piccpci != NULL )
  526. {
  527. piccpci->Release();
  528. } // if:
  529. if ( pcpc != NULL )
  530. {
  531. pcpc->Release();
  532. } // if:
  533. if ( pcp != NULL )
  534. {
  535. pcp->Release();
  536. } // if:
  537. if ( pcccb != NULL )
  538. {
  539. pcccb->Release();
  540. } // if:
  541. TraceSysFreeString( bstrNodeName );
  542. TraceSysFreeString( bstrDescription );
  543. TraceSysFreeString( bstrReference );
  544. TraceSysFreeString( bstrLastNodeName );
  545. TraceSysFreeString( bstrNodeConnectedTo );
  546. LogMsg( L"[MT] Polling callback task exiting. It %ws cancelled.", m_fStop == FALSE ? L"was not" : L"was" );
  547. HRETURN( hr );
  548. } //*** CTaskPollingCallback::BeginTask
  549. //////////////////////////////////////////////////////////////////////////////
  550. //++
  551. //
  552. // STDMETHODIMP
  553. // CTaskPollingCallback::StopTask( void )
  554. //
  555. //--
  556. //////////////////////////////////////////////////////////////////////////////
  557. STDMETHODIMP
  558. CTaskPollingCallback::StopTask( void )
  559. {
  560. TraceFunc( "[IDoTask]" );
  561. HRESULT hr = S_OK;
  562. m_fStop = true;
  563. HRETURN( hr );
  564. } //*** CTaskPollingCallback::StopTask
  565. //////////////////////////////////////////////////////////////////////////////
  566. //++
  567. //
  568. // STDMETHODIMP
  569. // CTaskPollingCallback::SetServerInfo(
  570. // DWORD dwRemoteServerObjectGITCookieIn
  571. // , OBJECTCOOKIE cookieLocalServerObjectIn
  572. // )
  573. //
  574. //--
  575. //////////////////////////////////////////////////////////////////////////////
  576. STDMETHODIMP
  577. CTaskPollingCallback::SetServerInfo(
  578. DWORD dwRemoteServerObjectGITCookieIn
  579. , OBJECTCOOKIE cookieLocalServerObjectIn
  580. )
  581. {
  582. TraceFunc( "[ITaskPollingCallback]" );
  583. HRESULT hr = S_OK;
  584. m_dwRemoteServerObjectGITCookie = dwRemoteServerObjectGITCookieIn;
  585. m_cookieLocalServerObject = cookieLocalServerObjectIn;
  586. HRETURN( hr );
  587. } //*** CTaskPollingCallback::SetServerInfo