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.

424 lines
11 KiB

  1. /******************************************************************************
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. helpsvc.cpp
  5. Abstract:
  6. Housekeeping for the HelpSvc service.
  7. Revision History:
  8. Davide Massarenti (Dmassare) 04/15/2001
  9. created
  10. ******************************************************************************/
  11. #include "stdafx.h"
  12. #include <idletask.h>
  13. ////////////////////////////////////////////////////////////////////////////////
  14. static const WCHAR s_szRoot [] = HC_REGISTRY_PCHSVC;
  15. static const WCHAR s_szStartItSrv [] = L"StartItSrv";
  16. static const WCHAR s_szDataCollection[] = L"DataCollection";
  17. typedef MPC::SmartLockGeneric<MPC::CComSafeAutoCriticalSection> LocalSmartLock;
  18. ////////////////////////////////////////////////////////////////////////////////
  19. #ifdef DEBUG
  20. static void StartIdleTaskServer()
  21. {
  22. MPC::wstring strValue;
  23. bool fFound;
  24. if(SUCCEEDED(MPC::RegKey_Value_Read( strValue, fFound, s_szRoot, s_szStartItSrv )) && fFound)
  25. {
  26. PROCESS_INFORMATION piProcessInformation;
  27. STARTUPINFOW siStartupInfo;
  28. BOOL fStarted;
  29. MPC::SubstituteEnvVariables( strValue );
  30. ::ZeroMemory( (PVOID)&piProcessInformation, sizeof( piProcessInformation ) );
  31. ::ZeroMemory( (PVOID)&siStartupInfo , sizeof( siStartupInfo ) ); siStartupInfo.cb = sizeof( siStartupInfo );
  32. fStarted = ::CreateProcessW( NULL ,
  33. (LPWSTR)strValue.c_str(),
  34. NULL ,
  35. NULL ,
  36. FALSE ,
  37. NORMAL_PRIORITY_CLASS ,
  38. NULL ,
  39. NULL ,
  40. &siStartupInfo ,
  41. &piProcessInformation );
  42. if(piProcessInformation.hProcess) ::CloseHandle( piProcessInformation.hProcess );
  43. if(piProcessInformation.hThread ) ::CloseHandle( piProcessInformation.hThread );
  44. }
  45. }
  46. #endif
  47. ////////////////////////////////////////////////////////////////////////////////
  48. ServiceHandler_HelpSvc::ServiceHandler_HelpSvc( /*[in]*/ LPCWSTR szServiceName, /*[in]*/ CComRedirectorFactory* rgClasses ) :
  49. ServiceHandler ( szServiceName, rgClasses ),
  50. m_svc_Timer ( this, ServiceShutdownCallback ),
  51. m_batch_Event ( this, BatchCallback ),
  52. m_batch_Timer ( this, BatchCallback2 ),
  53. m_dc_Timer ( this, DataCollectionCallback ),
  54. m_dc_TimerRestart( this, DataCollectionRestartCallback ),
  55. m_dc_EventStart ( this, IdleStartCallback , WT_EXECUTEONLYONCE ),
  56. m_dc_EventStop ( this, IdleStopCallback , WT_EXECUTEONLYONCE )
  57. {
  58. // MPC::CComSafeAutoCriticalSection m_cs;
  59. // CComPtr<IPCHService> m_svc;
  60. // LocalTimer m_svc_Timer;
  61. //
  62. m_batch_Notification = INVALID_HANDLE_VALUE; // HANDLE m_batch_Notification;
  63. // LocalEvent m_batch_Event;
  64. // LocalTimer m_batch_Timer;
  65. //
  66. // LocalTimer m_dc_Timer;
  67. // LocalTimer m_dc_TimerRestart;
  68. //
  69. m_dc_IdleHandle = NULL; // HANDLE m_dc_IdleHandle;
  70. m_dc_IdleStart = NULL; // HANDLE m_dc_IdleStart;
  71. m_dc_IdleStop = NULL; // HANDLE m_dc_IdleStop;
  72. // LocalEvent m_dc_EventStart;
  73. // LocalEvent m_dc_EventStop;
  74. }
  75. HRESULT ServiceHandler_HelpSvc::Initialize()
  76. {
  77. __MPC_FUNC_ENTRY( COMMONID, "ServiceHandler_HelpSvc::Initialize" );
  78. const DWORD s_dwNotify = FILE_NOTIFY_CHANGE_FILE_NAME |
  79. FILE_NOTIFY_CHANGE_DIR_NAME |
  80. FILE_NOTIFY_CHANGE_ATTRIBUTES |
  81. FILE_NOTIFY_CHANGE_SIZE |
  82. FILE_NOTIFY_CHANGE_CREATION;
  83. HRESULT hr;
  84. __MPC_EXIT_IF_METHOD_FAILS(hr, ServiceHandler::Initialize());
  85. try
  86. {
  87. {
  88. MPC::wstring strBatch( HC_ROOT_HELPSVC_BATCH ); MPC::SubstituteEnvVariables( strBatch );
  89. m_batch_Notification = ::FindFirstChangeNotificationW( strBatch.c_str(), TRUE, s_dwNotify );
  90. if(m_batch_Notification != INVALID_HANDLE_VALUE)
  91. {
  92. m_batch_Event.Attach( m_batch_Notification );
  93. m_batch_Event.Set ( INFINITE );
  94. }
  95. }
  96. DataCollection_Queue();
  97. }
  98. catch(...)
  99. {
  100. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  101. }
  102. hr = S_OK;
  103. __MPC_FUNC_CLEANUP;
  104. __MPC_FUNC_EXIT(hr);
  105. }
  106. void ServiceHandler_HelpSvc::Cleanup()
  107. {
  108. try
  109. {
  110. m_svc_Timer .Reset();
  111. m_dc_Timer .Reset();
  112. m_dc_TimerRestart.Reset();
  113. IdleTask_Cleanup();
  114. ////////////////////
  115. if(m_batch_Notification != INVALID_HANDLE_VALUE)
  116. {
  117. m_batch_Event.Attach( NULL );
  118. ::FindCloseChangeNotification( m_batch_Notification );
  119. m_batch_Notification = INVALID_HANDLE_VALUE;
  120. }
  121. ////////////////////
  122. //
  123. // Find the HelpSvc class factory and force a shutdown.
  124. //
  125. {
  126. CComRedirectorFactory* classes;
  127. for(classes=m_rgClasses; classes->m_pclsid; classes++)
  128. {
  129. IPCHService* svc;
  130. if(SUCCEEDED(classes->GetServer( NULL, __uuidof( IPCHService ), (void**)&svc )))
  131. {
  132. (void)svc->PrepareForShutdown();
  133. svc->Release();
  134. ::Sleep( 3000 ); // Give some time to shutdown code.
  135. }
  136. }
  137. }
  138. }
  139. catch(...)
  140. {
  141. }
  142. ServiceHandler::Cleanup();
  143. }
  144. ////////////////////////////////////////
  145. HRESULT ServiceHandler_HelpSvc::IdleTask_Initialize()
  146. {
  147. __MPC_FUNC_ENTRY( COMMONID, "ServiceHandler_HelpSvc::IdleTask_Initialize" );
  148. HRESULT hr;
  149. {
  150. LocalSmartLock lock( &m_cs );
  151. if(!m_dc_IdleHandle)
  152. {
  153. try
  154. {
  155. DWORD dwErr = ::RegisterIdleTask( ItHelpSvcDataCollectionTaskId, &m_dc_IdleHandle, &m_dc_IdleStart, &m_dc_IdleStop );
  156. #ifdef DEBUG
  157. if(dwErr != ERROR_SUCCESS)
  158. {
  159. StartIdleTaskServer();
  160. dwErr = ::RegisterIdleTask( ItHelpSvcDataCollectionTaskId, &m_dc_IdleHandle, &m_dc_IdleStart, &m_dc_IdleStop );
  161. }
  162. #endif
  163. __MPC_EXIT_IF_METHOD_FAILS(hr, HRESULT_FROM_WIN32(dwErr));
  164. lock = NULL; // Release lock before going into the Event code!!!
  165. m_dc_EventStart.Attach( m_dc_IdleStart );
  166. m_dc_EventStop .Attach( m_dc_IdleStop );
  167. m_dc_EventStart.Set( INFINITE );
  168. }
  169. catch(...)
  170. {
  171. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  172. }
  173. }
  174. }
  175. hr = S_OK;
  176. __MPC_FUNC_CLEANUP;
  177. __MPC_FUNC_EXIT(hr);
  178. }
  179. void ServiceHandler_HelpSvc::IdleTask_Cleanup()
  180. {
  181. try
  182. {
  183. m_dc_EventStart.Attach( NULL );
  184. m_dc_EventStop .Attach( NULL );
  185. {
  186. LocalSmartLock lock( &m_cs );
  187. if(m_dc_IdleHandle)
  188. {
  189. ::UnregisterIdleTask( m_dc_IdleHandle, m_dc_IdleStart, m_dc_IdleStop );
  190. m_dc_IdleHandle = NULL;
  191. m_dc_IdleStart = NULL;
  192. m_dc_IdleStop = NULL;
  193. }
  194. }
  195. }
  196. catch(...)
  197. {
  198. }
  199. }
  200. ////////////////////////////////////////
  201. HRESULT ServiceHandler_HelpSvc::DataCollection_Queue()
  202. {
  203. __MPC_FUNC_ENTRY( COMMONID, "ServiceHandler_HelpSvc::DataCollection_Queue" );
  204. MPC::wstring strValue;
  205. bool fFound;
  206. DWORD dwDelay = 10 * 1000;
  207. if(SUCCEEDED(MPC::RegKey_Value_Read( strValue, fFound, s_szRoot, s_szDataCollection )) && fFound)
  208. {
  209. DATE dDate;
  210. if(SUCCEEDED(MPC::ConvertStringToDate( strValue, dDate, /*fGMT*/false, /*fCIM*/true, 0 )))
  211. {
  212. const DATE c_OneDay = 1.0;
  213. const DATE c_MillisecInOneDay = 24.0 * 60.0 * 60.0 * 1000.0;
  214. DATE dDiff = c_OneDay - (MPC::GetLocalTime() - dDate);
  215. //
  216. // Wait at least six hours between DC.
  217. //
  218. if(dDiff > 0) dwDelay = dDiff * c_MillisecInOneDay;
  219. }
  220. }
  221. m_dc_Timer.Set( dwDelay, 0 );
  222. return S_OK;
  223. }
  224. HRESULT ServiceHandler_HelpSvc::DataCollection_Execute( /*[in]*/ bool fCancel )
  225. {
  226. if(!fCancel) ConnectToServer();
  227. {
  228. LocalSmartLock lock( &m_cs );
  229. if(m_svc)
  230. {
  231. m_svc->TriggerScheduledDataCollection( fCancel ? VARIANT_FALSE : VARIANT_TRUE );
  232. lock = NULL; // Release lock before going into the Timer code!!!
  233. m_svc_Timer.Set( 60 * 1000, 0 );
  234. }
  235. }
  236. m_dc_TimerRestart.Set( 1 * 1000, 0 );
  237. return S_OK;
  238. }
  239. ////////////////////////////////////////
  240. void ServiceHandler_HelpSvc::ConnectToServer()
  241. {
  242. {
  243. LocalSmartLock lock( &m_cs );
  244. if(!m_svc)
  245. {
  246. m_svc.CoCreateInstance( CLSID_PCHService );
  247. }
  248. }
  249. m_svc_Timer.Set( 60 * 1000, 0 );
  250. }
  251. ////////////////////////////////////////
  252. HRESULT ServiceHandler_HelpSvc::ServiceShutdownCallback( /*[in]*/ BOOLEAN TimerOrWaitFired )
  253. {
  254. {
  255. LocalSmartLock lock( &m_cs );
  256. m_svc.Release();
  257. }
  258. DataCollection_Queue();
  259. return S_OK;
  260. }
  261. HRESULT ServiceHandler_HelpSvc::BatchCallback( /*[in]*/ BOOLEAN TimerOrWaitFired )
  262. {
  263. m_batch_Timer.Set( 5000, 0 );
  264. {
  265. LocalSmartLock lock( &m_cs );
  266. ::FindNextChangeNotification( m_batch_Notification );
  267. }
  268. return S_OK;
  269. }
  270. HRESULT ServiceHandler_HelpSvc::BatchCallback2( /*[in]*/ BOOLEAN TimerOrWaitFired )
  271. {
  272. //
  273. // If not already running, start it.
  274. //
  275. ConnectToServer();
  276. return S_OK;
  277. }
  278. ////////////////////////////////////////
  279. HRESULT ServiceHandler_HelpSvc::DataCollectionCallback( /*[in]*/ BOOLEAN TimerOrWaitFired )
  280. {
  281. MPC::wstring strDate;
  282. if(FAILED(IdleTask_Initialize()))
  283. {
  284. DataCollection_Execute( /*fCancel*/false );
  285. }
  286. if(SUCCEEDED(MPC::ConvertDateToString( MPC::GetLocalTime(), strDate, /*fGMT*/false, /*fCIM*/true, 0 )))
  287. {
  288. (void)MPC::RegKey_Value_Write( strDate, s_szRoot, s_szDataCollection );
  289. }
  290. return S_OK;
  291. }
  292. HRESULT ServiceHandler_HelpSvc::DataCollectionRestartCallback( /*[in]*/ BOOLEAN TimerOrWaitFired )
  293. {
  294. DataCollection_Queue();
  295. return S_OK;
  296. }
  297. HRESULT ServiceHandler_HelpSvc::IdleStartCallback( /*[in]*/ BOOLEAN TimerOrWaitFired )
  298. {
  299. m_dc_EventStart.Reset( );
  300. m_dc_EventStop .Set ( INFINITE );
  301. DataCollection_Execute( /*fCancel*/false );
  302. IdleTask_Cleanup();
  303. return S_OK;
  304. }
  305. HRESULT ServiceHandler_HelpSvc::IdleStopCallback( /*[in]*/ BOOLEAN TimerOrWaitFired )
  306. {
  307. m_dc_EventStop .Reset( );
  308. m_dc_EventStart.Set ( INFINITE );
  309. DataCollection_Execute( /*fCancel*/true );
  310. return S_OK;
  311. }