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.

757 lines
20 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. module.cpp
  5. Abstract:
  6. This file contains the implementation of the CServiceModule class, which is
  7. used to handling service-related routines.
  8. Revision History:
  9. Davide Massarenti (Dmassare) 03/14/2000
  10. created
  11. ******************************************************************************/
  12. #include "stdafx.h"
  13. /////////////////////////////////////////////////////////////////////////////
  14. DWORD dwTimeOut = 8*1000; // time for EXE to be idle before shutting down
  15. const DWORD dwPause = 1000; // time to wait for threads to finish up
  16. CServiceModule _Module;
  17. MPC::NTEvent g_NTEvents;
  18. CMPCConfig g_Config;
  19. /////////////////////////////////////////////////////////////////////////////
  20. //
  21. // These variables control the overriding of properties for debug.
  22. //
  23. bool g_Override_History = false;
  24. UL_HISTORY g_Override_History_Value = UL_HISTORY_NONE;
  25. bool g_Override_Persist = false;
  26. VARIANT_BOOL g_Override_Persist_Value = false;
  27. bool g_Override_Compressed = false;
  28. VARIANT_BOOL g_Override_Compressed_Value = false;
  29. ////////////////////////////////////////////////////////////////////////////////
  30. ////////////////////////////////////////////////////////////////////////////////
  31. const WCHAR c_szMessageFile [] = L"%WINDIR%\\PCHealth\\UploadLB\\Binaries\\UploadM.exe";
  32. const WCHAR c_szRegistryLog [] = L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\UploadM";
  33. const WCHAR c_szRegistryLog_File [] = L"EventMessageFile";
  34. const WCHAR c_szRegistryLog_Flags[] = L"TypesSupported";
  35. /////////////////////////////////////////////////////////////////////////////
  36. /////////////////////////////////////////////////////////////////////////////
  37. #ifdef DEBUG
  38. #define DEBUG_REGKEY L"SOFTWARE\\Microsoft\\PCHealth\\UploadM\\Debug"
  39. #define DEBUG_TIMEOUT L"TIMEOUT"
  40. #define DEBUG_BREAKONSTART L"BREAKONSTART"
  41. #define DEBUG_HISTORY L"HISTORY"
  42. #define DEBUG_PERSIST L"PERSIST"
  43. #define DEBUG_COMPRESSED L"COMPRESSED"
  44. void CServiceModule::ReadDebugSettings()
  45. {
  46. __ULT_FUNC_ENTRY( "CServiceModule::ReadDebugSettings" );
  47. HRESULT hr;
  48. MPC::RegKey rkBase;
  49. bool fFound;
  50. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.SetRoot( HKEY_LOCAL_MACHINE ));
  51. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.Attach ( DEBUG_REGKEY ));
  52. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.Exists ( fFound ));
  53. if(fFound)
  54. {
  55. CComVariant vValue;
  56. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.get_Value( vValue, fFound, DEBUG_BREAKONSTART ));
  57. if(fFound && vValue.vt == VT_I4)
  58. {
  59. if(vValue.lVal == 1) DebugBreak();
  60. if(vValue.lVal == 2) while(vValue.lVal) ::Sleep( 100 );
  61. }
  62. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.get_Value( vValue, fFound, DEBUG_TIMEOUT ));
  63. if(fFound && vValue.vt == VT_I4)
  64. {
  65. dwTimeOut = 1000 * vValue.lVal;
  66. }
  67. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.get_Value( vValue, fFound, DEBUG_HISTORY ));
  68. if(fFound && vValue.vt == VT_I4 && vValue.lVal != -1)
  69. {
  70. g_Override_History = true;
  71. g_Override_History_Value = (UL_HISTORY)vValue.lVal;
  72. }
  73. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.get_Value( vValue, fFound, DEBUG_PERSIST ));
  74. if(fFound && vValue.vt == VT_I4 && vValue.lVal != -1)
  75. {
  76. g_Override_Persist = true;
  77. g_Override_Persist_Value = vValue.lVal ? VARIANT_TRUE : VARIANT_FALSE;
  78. }
  79. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.get_Value( vValue, fFound, DEBUG_COMPRESSED ));
  80. if(fFound && vValue.vt == VT_I4 && vValue.lVal != -1)
  81. {
  82. g_Override_Compressed = true;
  83. g_Override_Compressed_Value = vValue.lVal ? VARIANT_TRUE : VARIANT_FALSE;
  84. }
  85. }
  86. __ULT_FUNC_CLEANUP;
  87. }
  88. #endif
  89. /////////////////////////////////////////////////////////////////////////////
  90. static const WCHAR s_SvcHost[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Svchost";
  91. static const WCHAR s_Key [] = L"System\\CurrentControlSet\\Services\\%s";
  92. static const WCHAR s_Key2 [] = L"\\Parameters";
  93. static const WCHAR s_Name [] = L"ServiceDll";
  94. static const WCHAR s_Value[] = L"%WINDIR%\\PCHealth\\HelpCtr\\Binaries\\pchsvc.dll";
  95. static HRESULT ServiceHost_Install( LPCWSTR szName, LPCWSTR szGroup )
  96. {
  97. __ULT_FUNC_ENTRY( "ServiceHost_Install" );
  98. HRESULT hr;
  99. //
  100. // Register the message file into the registry.
  101. //
  102. {
  103. MPC::wstring szPath ( c_szMessageFile ); MPC::SubstituteEnvVariables( szPath );
  104. MPC::RegKey rkEventLog;
  105. CComVariant vValue;
  106. __MPC_EXIT_IF_METHOD_FAILS(hr, rkEventLog.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS ));
  107. __MPC_EXIT_IF_METHOD_FAILS(hr, rkEventLog.Attach ( c_szRegistryLog ));
  108. __MPC_EXIT_IF_METHOD_FAILS(hr, rkEventLog.Create ( ));
  109. vValue = szPath.c_str(); __MPC_EXIT_IF_METHOD_FAILS(hr, rkEventLog.put_Value( vValue, c_szRegistryLog_File ));
  110. vValue = (long)0x1F ; __MPC_EXIT_IF_METHOD_FAILS(hr, rkEventLog.put_Value( vValue, c_szRegistryLog_Flags ));
  111. }
  112. {
  113. WCHAR rgRegPath[_MAX_PATH]; swprintf( rgRegPath, s_Key, szName ); wcscat( rgRegPath, s_Key2 );
  114. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::RegKey_Value_Write( s_Value, rgRegPath, s_Name, HKEY_LOCAL_MACHINE, true ));
  115. }
  116. {
  117. MPC::RegKey rk;
  118. MPC::WStringList lstValue;
  119. bool fFound;
  120. bool fGot = false;
  121. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS ));
  122. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.Attach ( s_SvcHost ));
  123. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.Create ( ));
  124. if(SUCCEEDED(rk.Read( lstValue, fFound, szGroup )))
  125. {
  126. for(MPC::WStringIterConst it = lstValue.begin(); it != lstValue.end(); it++)
  127. {
  128. if(!MPC::StrICmp( *it, szName ))
  129. {
  130. fGot = true;
  131. break;
  132. }
  133. }
  134. }
  135. if(fGot == false)
  136. {
  137. lstValue.push_back( szName );
  138. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.Write( lstValue, szGroup ));
  139. }
  140. }
  141. hr = S_OK;
  142. __ULT_FUNC_CLEANUP;
  143. __ULT_FUNC_EXIT(hr);
  144. }
  145. static HRESULT ServiceHost_Uninstall( LPCWSTR szName, LPCWSTR szGroup )
  146. {
  147. __ULT_FUNC_ENTRY( "ServiceHost_Uninstall" );
  148. HRESULT hr;
  149. {
  150. WCHAR rgRegPath[_MAX_PATH]; swprintf( rgRegPath, s_Key, szName );
  151. MPC::RegKey rk;
  152. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS ));
  153. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.Attach ( rgRegPath ));
  154. (void)rk.Delete( /*fDeep*/true );
  155. }
  156. {
  157. MPC::RegKey rk;
  158. MPC::WStringList lstValue;
  159. bool fFound;
  160. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS ));
  161. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.Attach ( s_SvcHost ));
  162. if(SUCCEEDED(rk.Read( lstValue, fFound, szGroup )))
  163. {
  164. MPC::WStringIterConst it = lstValue.begin();
  165. bool fGot = false;
  166. while(it != lstValue.end())
  167. {
  168. MPC::WStringIterConst it2 = it++;
  169. if(!MPC::StrICmp( *it2, szName ))
  170. {
  171. lstValue.erase( it2 );
  172. fGot = true;
  173. }
  174. }
  175. if(fGot)
  176. {
  177. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.Write( lstValue, szGroup ));
  178. }
  179. }
  180. }
  181. hr = S_OK;
  182. __ULT_FUNC_CLEANUP;
  183. __ULT_FUNC_EXIT(hr);
  184. }
  185. /////////////////////////////////////////////////////////////////////////////
  186. CServiceModule::CServiceModule()
  187. {
  188. m_hEventShutdown = NULL; // HANDLE m_hEventShutdown;
  189. m_dwThreadID = 0; // DWORD m_dwThreadID;
  190. m_hMonitor = NULL; // HANDLE m_hMonitor;
  191. m_bActivity = FALSE; // BOOL m_bActivity;
  192. //
  193. m_szServiceName = NULL; // LPCWSTR m_szServiceName;
  194. m_iDisplayName = 0; // UINT m_iDisplayName;
  195. m_iDescription = 0; // UINT m_iDescription;
  196. m_hServiceStatus = NULL; // SERVICE_STATUS_HANDLE m_hServiceStatus;
  197. // SERVICE_STATUS m_status;
  198. m_bService = FALSE; // BOOL m_bService;
  199. ::ZeroMemory( &m_status, sizeof( m_status ) );
  200. }
  201. CServiceModule::~CServiceModule()
  202. {
  203. if(m_hEventShutdown) ::CloseHandle( m_hEventShutdown );
  204. if(m_hMonitor ) ::CloseHandle( m_hMonitor );
  205. }
  206. /////////////////////////////////////////////////////////////////////////////
  207. LONG CServiceModule::Lock()
  208. {
  209. LONG lCount = CComModule::Lock();
  210. return lCount;
  211. }
  212. LONG CServiceModule::Unlock()
  213. {
  214. LONG lCount = CComModule::Unlock();
  215. if(lCount == 0)
  216. {
  217. m_bActivity = TRUE;
  218. if(m_hEventShutdown) ::SetEvent( m_hEventShutdown ); // tell monitor that we transitioned to zero
  219. }
  220. return lCount;
  221. }
  222. void CServiceModule::MonitorShutdown()
  223. {
  224. while(1)
  225. {
  226. DWORD dwWait;
  227. m_bActivity = FALSE;
  228. dwWait = ::WaitForSingleObject( m_hEventShutdown, dwTimeOut );
  229. if(dwWait == WAIT_OBJECT_0) continue; // We are alive...
  230. if(g_Root.CanContinue()) continue;
  231. //
  232. // If no activity let's really bail.
  233. //
  234. if(m_bActivity == FALSE && m_nLockCnt <= 0)
  235. {
  236. ::CoSuspendClassObjects();
  237. if(m_bActivity == FALSE && m_nLockCnt <= 0) break;
  238. }
  239. }
  240. ForceShutdown();
  241. }
  242. void CServiceModule::ForceShutdown()
  243. {
  244. //
  245. // Tell process to exit.
  246. //
  247. ::PostThreadMessage( m_dwThreadID, WM_QUIT, 0, 0 );
  248. }
  249. BOOL CServiceModule::StartMonitor()
  250. {
  251. DWORD dwThreadID;
  252. m_hMonitor = ::CreateThread( NULL, 0, _Monitor, this, 0, &dwThreadID );
  253. if(m_hMonitor == NULL) return FALSE;
  254. return TRUE;
  255. }
  256. /////////////////////////////////////////////////////////////////////////////
  257. HRESULT CServiceModule::RegisterServer( BOOL bRegTypeLib, BOOL bService, LPCWSTR szSvcHostGroup )
  258. {
  259. HRESULT hr;
  260. // Remove any previous service since it may point to the incorrect file
  261. Uninstall( szSvcHostGroup );
  262. if(bService)
  263. {
  264. // Create service
  265. Install( szSvcHostGroup );
  266. }
  267. // Add object entries
  268. if(FAILED(hr = CComModule::RegisterServer( TRUE ))) return hr;
  269. if(FAILED(hr = _Module.UpdateRegistryFromResource( IDR_UPLOADMANAGER, TRUE ))) return hr;
  270. return S_OK;
  271. }
  272. HRESULT CServiceModule::UnregisterServer( LPCWSTR szSvcHostGroup )
  273. {
  274. HRESULT hr;
  275. // Remove service
  276. Uninstall( szSvcHostGroup );
  277. // Remove object entries
  278. if(FAILED(hr = CComModule::UnregisterServer( TRUE ))) return hr;
  279. if(FAILED(hr = _Module.UpdateRegistryFromResource( IDR_UPLOADMANAGER, FALSE ))) return hr;
  280. return S_OK;
  281. }
  282. void CServiceModule::Init( _ATL_OBJMAP_ENTRY* p, HINSTANCE h, LPCWSTR szServiceName, UINT iDisplayName, UINT iDescription, const GUID* plibid )
  283. {
  284. CComModule::Init( p, h, plibid );
  285. m_szServiceName = szServiceName;
  286. m_iDisplayName = iDisplayName;
  287. m_iDescription = iDescription;
  288. // set up the initial service status
  289. m_hServiceStatus = NULL;
  290. m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  291. m_status.dwCurrentState = SERVICE_STOPPED;
  292. m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  293. m_status.dwWin32ExitCode = 0;
  294. m_status.dwServiceSpecificExitCode = 0;
  295. m_status.dwCheckPoint = 0;
  296. m_status.dwWaitHint = 0;
  297. }
  298. BOOL CServiceModule::IsInstalled()
  299. {
  300. BOOL bResult = FALSE;
  301. SC_HANDLE hSCM = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
  302. if((hSCM = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS )))
  303. {
  304. SC_HANDLE hService;
  305. if((hService = ::OpenServiceW( hSCM, m_szServiceName, SERVICE_QUERY_CONFIG )))
  306. {
  307. bResult = TRUE;
  308. ::CloseServiceHandle( hService );
  309. }
  310. ::CloseServiceHandle( hSCM );
  311. }
  312. return bResult;
  313. }
  314. BOOL CServiceModule::Install( LPCWSTR szSvcHostGroup )
  315. {
  316. BOOL bResult = FALSE;
  317. SC_HANDLE hSCM;
  318. if((hSCM = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS )))
  319. {
  320. LPCWSTR szDisplayName;
  321. WCHAR rgDisplayName[512];
  322. WCHAR rgDescription[512];
  323. WCHAR rgFilePath [_MAX_PATH];
  324. SC_HANDLE hService;
  325. DWORD dwServiceType;
  326. OSVERSIONINFOEXW ver;
  327. DWORD dwStartType;
  328. if(szSvcHostGroup)
  329. {
  330. dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  331. swprintf( rgFilePath, L"%%SystemRoot%%\\System32\\svchost.exe -k %s", szSvcHostGroup );
  332. }
  333. else
  334. {
  335. dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  336. ::GetModuleFileNameW( NULL, rgFilePath, _MAX_PATH );
  337. }
  338. if(::LoadStringW( _Module.GetResourceInstance(), m_iDisplayName, rgDisplayName, MAXSTRLEN(rgDisplayName) ) != 0)
  339. {
  340. szDisplayName = rgDisplayName;
  341. }
  342. else
  343. {
  344. szDisplayName = m_szServiceName;
  345. }
  346. if(::LoadStringW( _Module.GetResourceInstance(), m_iDescription, rgDescription, MAXSTRLEN(rgDescription) ) == 0)
  347. {
  348. rgDescription[0] = 0;
  349. }
  350. ::ZeroMemory( &ver, sizeof(ver) ); ver.dwOSVersionInfoSize = sizeof(ver);
  351. ::GetVersionExW( (LPOSVERSIONINFOW)&ver );
  352. if(ver.wSuiteMask & VER_SUITE_DATACENTER)
  353. {
  354. dwStartType = SERVICE_DISABLED;
  355. }
  356. else
  357. {
  358. dwStartType = SERVICE_DEMAND_START;
  359. }
  360. hService = ::OpenServiceW( hSCM, m_szServiceName, SERVICE_QUERY_CONFIG );
  361. if(hService == NULL)
  362. {
  363. hService = ::CreateServiceW( hSCM ,
  364. m_szServiceName ,
  365. szDisplayName ,
  366. SERVICE_ALL_ACCESS ,
  367. dwServiceType ,
  368. dwStartType ,
  369. SERVICE_ERROR_NORMAL,
  370. rgFilePath ,
  371. NULL ,
  372. NULL ,
  373. L"RPCSS\0" ,
  374. NULL ,
  375. NULL );
  376. }
  377. if(hService)
  378. {
  379. if(rgDescription[0])
  380. {
  381. SERVICE_DESCRIPTIONW desc; ::ZeroMemory( &desc , sizeof(desc ) );
  382. SERVICE_FAILURE_ACTIONSW recovery; ::ZeroMemory( &recovery, sizeof(recovery) );
  383. SC_ACTION actions[] =
  384. {
  385. { SC_ACTION_RESTART, 100 },
  386. { SC_ACTION_RESTART, 100 },
  387. { SC_ACTION_NONE , 100 },
  388. };
  389. desc.lpDescription = rgDescription;
  390. recovery.dwResetPeriod = 24 * 60 * 60; // 1 day
  391. recovery.cActions = ARRAYSIZE(actions);
  392. recovery.lpsaActions = actions;
  393. ::ChangeServiceConfig2W( hService, SERVICE_CONFIG_DESCRIPTION , &desc );
  394. ::ChangeServiceConfig2W( hService, SERVICE_CONFIG_FAILURE_ACTIONS, &recovery );
  395. }
  396. if(szSvcHostGroup)
  397. {
  398. if(SUCCEEDED(ServiceHost_Install( m_szServiceName, szSvcHostGroup )))
  399. {
  400. bResult = TRUE;
  401. }
  402. }
  403. else
  404. {
  405. bResult = TRUE;
  406. }
  407. ::CloseServiceHandle( hService );
  408. }
  409. if(bResult == FALSE)
  410. {
  411. (void)g_NTEvents.LogEvent( EVENTLOG_ERROR_TYPE, UPLOADM_ERR_CANNOTCREATESERVICE, NULL );
  412. }
  413. ::CloseServiceHandle( hSCM );
  414. }
  415. else
  416. {
  417. (void)g_NTEvents.LogEvent( EVENTLOG_ERROR_TYPE, UPLOADM_ERR_CANNOTOPENSCM, NULL );
  418. }
  419. return bResult;
  420. }
  421. BOOL CServiceModule::Uninstall( LPCWSTR szSvcHostGroup )
  422. {
  423. BOOL bResult = FALSE;
  424. SC_HANDLE hSCM;
  425. if((hSCM = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS )))
  426. {
  427. SC_HANDLE hService;
  428. if((hService = ::OpenServiceW( hSCM, m_szServiceName, SERVICE_STOP | DELETE )))
  429. {
  430. SERVICE_STATUS status;
  431. ::ControlService( hService, SERVICE_CONTROL_STOP, &status );
  432. bResult = ::DeleteService( hService );
  433. if(bResult)
  434. {
  435. ::Sleep( 2000 ); // Let the service stop down...
  436. if(szSvcHostGroup)
  437. {
  438. if(FAILED(ServiceHost_Uninstall( m_szServiceName, szSvcHostGroup )))
  439. {
  440. bResult = FALSE;
  441. }
  442. }
  443. }
  444. if(bResult == FALSE)
  445. {
  446. (void)g_NTEvents.LogEvent( EVENTLOG_ERROR_TYPE, UPLOADM_ERR_CANNOTDELETESERVICE, NULL );
  447. }
  448. ::CloseServiceHandle( hService );
  449. }
  450. ::CloseServiceHandle( hSCM );
  451. }
  452. else
  453. {
  454. (void)g_NTEvents.LogEvent( EVENTLOG_ERROR_TYPE, UPLOADM_ERR_CANNOTOPENSCM, NULL );
  455. }
  456. return bResult;
  457. }
  458. //////////////////////////////////////////////////////////////////////////////////////////////
  459. // Service startup and registration
  460. BOOL CServiceModule::Start( BOOL bService )
  461. {
  462. SERVICE_TABLE_ENTRYW st[] =
  463. {
  464. { (LPWSTR)m_szServiceName, _ServiceMain },
  465. { NULL , NULL }
  466. };
  467. m_hEventShutdown = ::CreateEvent( NULL, FALSE, FALSE, NULL );
  468. if(m_hEventShutdown == NULL) return FALSE;
  469. if((m_bService = bService) && !::StartServiceCtrlDispatcherW( st ))
  470. {
  471. DWORD dwRes = ::GetLastError();
  472. m_bService = FALSE;
  473. }
  474. if(m_bService == FALSE)
  475. {
  476. if(StartMonitor() == FALSE) return FALSE;
  477. if(FAILED(Run())) return FALSE;
  478. }
  479. return TRUE;
  480. }
  481. void CServiceModule::ServiceMain( DWORD dwArgc, LPWSTR lpszArgv[] )
  482. {
  483. // Register the control request handler
  484. m_status.dwCurrentState = SERVICE_START_PENDING;
  485. if((m_hServiceStatus = ::RegisterServiceCtrlHandlerW( m_szServiceName, _Handler )))
  486. {
  487. SetServiceStatus( SERVICE_START_PENDING );
  488. m_status.dwWin32ExitCode = S_OK;
  489. m_status.dwCheckPoint = 0;
  490. m_status.dwWaitHint = 0;
  491. // When the Run function returns, the service has stopped.
  492. Run();
  493. SetServiceStatus( SERVICE_STOPPED );
  494. (void)g_NTEvents.LogEvent( EVENTLOG_INFORMATION_TYPE, UPLOADM_INFO_STOPPED, NULL );
  495. }
  496. else
  497. {
  498. (void)g_NTEvents.LogEvent( EVENTLOG_ERROR_TYPE, UPLOADM_ERR_REGISTERHANDLER, NULL );
  499. }
  500. }
  501. void CServiceModule::Handler( DWORD dwOpcode )
  502. {
  503. switch(dwOpcode)
  504. {
  505. case SERVICE_CONTROL_STOP:
  506. SetServiceStatus( SERVICE_STOP_PENDING );
  507. ForceShutdown();
  508. break;
  509. case SERVICE_CONTROL_PAUSE:
  510. break;
  511. case SERVICE_CONTROL_CONTINUE:
  512. break;
  513. case SERVICE_CONTROL_INTERROGATE:
  514. break;
  515. case SERVICE_CONTROL_SHUTDOWN:
  516. break;
  517. default:
  518. (void)g_NTEvents.LogEvent( EVENTLOG_ERROR_TYPE, UPLOADM_ERR_BADSVCREQUEST, NULL );
  519. }
  520. }
  521. HRESULT CServiceModule::Run()
  522. {
  523. __ULT_FUNC_ENTRY( "CServiceModule::Run" );
  524. HRESULT hr;
  525. MSG msg;
  526. m_dwThreadID = ::GetCurrentThreadId();
  527. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoInitializeEx( NULL, COINIT_MULTITHREADED )); // We need to be a multi-threaded application.
  528. __MPC_EXIT_IF_METHOD_FAILS(hr, RegisterClassObjects( CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE ));
  529. (void)g_NTEvents.LogEvent( EVENTLOG_INFORMATION_TYPE, UPLOADM_INFO_STARTED, NULL );
  530. if(m_bService)
  531. {
  532. SetServiceStatus( SERVICE_RUNNING );
  533. }
  534. //
  535. // Load the state of the queue.
  536. //
  537. __MPC_EXIT_IF_METHOD_FAILS(hr, g_Root.Init());
  538. while(::GetMessage( &msg, 0, 0, 0 ))
  539. {
  540. ::DispatchMessage( &msg );
  541. }
  542. _Module.RevokeClassObjects();
  543. ::Sleep( dwPause ); //wait for any threads to finish
  544. hr = S_OK;
  545. __ULT_FUNC_CLEANUP;
  546. __ULT_FUNC_EXIT(hr);
  547. }
  548. void CServiceModule::SetServiceStatus( DWORD dwState )
  549. {
  550. m_status.dwCurrentState = dwState;
  551. ::SetServiceStatus( m_hServiceStatus, &m_status );
  552. }
  553. ////////////////////////////////////////////////////////////////////////////////
  554. void WINAPI CServiceModule::_ServiceMain( DWORD dwArgc, LPWSTR* lpszArgv )
  555. {
  556. _Module.ServiceMain( dwArgc, lpszArgv );
  557. }
  558. void WINAPI CServiceModule::_Handler( DWORD dwOpcode )
  559. {
  560. _Module.Handler( dwOpcode );
  561. }
  562. DWORD WINAPI CServiceModule::_Monitor( void* pv )
  563. {
  564. ((CServiceModule*)pv)->MonitorShutdown();
  565. return 0;
  566. }