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.

275 lines
6.3 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 COM server-related routines.
  8. Revision History:
  9. Davide Massarenti (Dmassare) 03/27/2000
  10. created
  11. ******************************************************************************/
  12. #include "stdafx.h"
  13. /////////////////////////////////////////////////////////////////////////////
  14. DWORD dwTimeOut = 10*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. /////////////////////////////////////////////////////////////////////////////
  19. #ifdef DEBUG
  20. #define DEBUG_REGKEY HC_REGISTRY_HELPHOST L"\\Debug"
  21. #define DEBUG_BREAKONSTART L"BREAKONSTART"
  22. #define DEBUG_TIMEOUT L"TIMEOUT"
  23. void CServiceModule::ReadDebugSettings()
  24. {
  25. __HCP_FUNC_ENTRY( "CServiceModule::ReadDebugSettings" );
  26. HRESULT hr;
  27. MPC::RegKey rkBase;
  28. bool fFound;
  29. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.SetRoot( HKEY_LOCAL_MACHINE ));
  30. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.Attach ( DEBUG_REGKEY ));
  31. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.Exists ( fFound ));
  32. if(fFound)
  33. {
  34. CComVariant vValue;
  35. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.get_Value( vValue, fFound, DEBUG_BREAKONSTART ));
  36. if(fFound && vValue.vt == VT_I4)
  37. {
  38. if(vValue.lVal) DebugBreak();
  39. }
  40. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.get_Value( vValue, fFound, DEBUG_TIMEOUT ));
  41. if(fFound && vValue.vt == VT_I4)
  42. {
  43. dwTimeOut = 1000 * vValue.lVal;
  44. }
  45. }
  46. __HCP_FUNC_CLEANUP;
  47. }
  48. #endif
  49. /////////////////////////////////////////////////////////////////////////////
  50. CServiceModule::CServiceModule()
  51. {
  52. m_hEventShutdown = NULL; // HANDLE m_hEventShutdown;
  53. m_dwThreadID = 0; // DWORD m_dwThreadID;
  54. m_hMonitor = NULL; // HANDLE m_hMonitor;
  55. m_bActivity = FALSE; // BOOL m_bActivity;
  56. //
  57. m_szServiceName = NULL; // LPCWSTR m_szServiceName;
  58. m_iDisplayName = 0; // UINT m_iDisplayName;
  59. m_iDescription = 0; // UINT m_iDescription;
  60. m_hServiceStatus = NULL; // SERVICE_STATUS_HANDLE m_hServiceStatus;
  61. // SERVICE_STATUS m_status;
  62. m_bService = FALSE; // BOOL m_bService;
  63. ::ZeroMemory( &m_status, sizeof( m_status ) );
  64. }
  65. CServiceModule::~CServiceModule()
  66. {
  67. if(m_hEventShutdown) ::CloseHandle( m_hEventShutdown );
  68. if(m_hMonitor ) ::CloseHandle( m_hMonitor );
  69. }
  70. /////////////////////////////////////////////////////////////////////////////
  71. LONG CServiceModule::Lock()
  72. {
  73. LONG lCount = CComModule::Lock();
  74. return lCount;
  75. }
  76. LONG CServiceModule::Unlock()
  77. {
  78. LONG lCount = CComModule::Unlock();
  79. if(lCount == 0)
  80. {
  81. m_bActivity = TRUE;
  82. if(m_hEventShutdown) ::SetEvent( m_hEventShutdown ); // tell monitor that we transitioned to zero
  83. }
  84. return lCount;
  85. }
  86. void CServiceModule::MonitorShutdown()
  87. {
  88. while(1)
  89. {
  90. DWORD dwWait;
  91. m_bActivity = FALSE;
  92. dwWait = ::WaitForSingleObject( m_hEventShutdown, dwTimeOut );
  93. if(dwWait == WAIT_OBJECT_0) continue; // We are alive...
  94. //
  95. // If no activity let's really bail.
  96. //
  97. if(m_bActivity == FALSE && m_nLockCnt <= 0)
  98. {
  99. ::CoSuspendClassObjects();
  100. if(m_bActivity == FALSE && m_nLockCnt <= 0) break;
  101. }
  102. }
  103. ForceShutdown();
  104. }
  105. void CServiceModule::ForceShutdown()
  106. {
  107. //
  108. // Tell process to exit.
  109. //
  110. ::PostThreadMessage( m_dwThreadID, WM_QUIT, 0, 0 );
  111. }
  112. BOOL CServiceModule::StartMonitor()
  113. {
  114. DWORD dwThreadID;
  115. m_hMonitor = ::CreateThread( NULL, 0, _Monitor, this, 0, &dwThreadID );
  116. if(m_hMonitor == NULL) return FALSE;
  117. return TRUE;
  118. }
  119. /////////////////////////////////////////////////////////////////////////////
  120. HRESULT CServiceModule::RegisterServer( BOOL bRegTypeLib, BOOL bService, LPCWSTR szSvcHostGroup )
  121. {
  122. HRESULT hr;
  123. // Add object entries
  124. if(FAILED(hr = CComModule::RegisterServer( FALSE ))) return hr;
  125. return S_OK;
  126. }
  127. HRESULT CServiceModule::UnregisterServer( LPCWSTR szSvcHostGroup )
  128. {
  129. HRESULT hr;
  130. // Remove object entries
  131. if(FAILED(hr = CComModule::UnregisterServer( FALSE ))) return hr;
  132. return S_OK;
  133. }
  134. void CServiceModule::Init( _ATL_OBJMAP_ENTRY* p, HINSTANCE h, LPCWSTR szServiceName, UINT iDisplayName, UINT iDescription, const GUID* plibid )
  135. {
  136. CComModule::Init( p, h, plibid );
  137. }
  138. BOOL CServiceModule::IsInstalled()
  139. {
  140. return FALSE; // Not implemented for a COM server.
  141. }
  142. BOOL CServiceModule::Install( LPCWSTR szSvcHostGroup )
  143. {
  144. return FALSE; // Not implemented for a COM server.
  145. }
  146. BOOL CServiceModule::Uninstall( LPCWSTR szSvcHostGroup )
  147. {
  148. return FALSE; // Not implemented for a COM server.
  149. }
  150. //////////////////////////////////////////////////////////////////////////////////////////////
  151. // Service startup and registration
  152. BOOL CServiceModule::Start( BOOL bService )
  153. {
  154. m_hEventShutdown = ::CreateEvent( NULL, FALSE, FALSE, NULL );
  155. if(m_hEventShutdown == NULL) return FALSE;
  156. if(StartMonitor() == FALSE) return FALSE;
  157. if(FAILED(Run())) return FALSE;
  158. return TRUE;
  159. }
  160. void CServiceModule::ServiceMain( DWORD dwArgc, LPWSTR lpszArgv[] )
  161. {
  162. // Not implemented.
  163. }
  164. void CServiceModule::Handler( DWORD dwOpcode )
  165. {
  166. // Not implemented.
  167. }
  168. HRESULT CServiceModule::Run()
  169. {
  170. __HCP_FUNC_ENTRY( "CServiceModule::Run" );
  171. HRESULT hr;
  172. MSG msg;
  173. m_dwThreadID = ::GetCurrentThreadId();
  174. while(::GetMessage( &msg, 0, 0, 0 ))
  175. {
  176. ::DispatchMessage( &msg );
  177. }
  178. hr = S_OK;
  179. _Module.RevokeClassObjects();
  180. ::Sleep( dwPause ); //wait for any threads to finish
  181. __HCP_FUNC_EXIT(hr);
  182. }
  183. void CServiceModule::SetServiceStatus( DWORD dwState )
  184. {
  185. // Not implemented.
  186. }
  187. ////////////////////////////////////////////////////////////////////////////////
  188. void WINAPI CServiceModule::_ServiceMain( DWORD dwArgc, LPWSTR* lpszArgv )
  189. {
  190. // Not implemented.
  191. }
  192. void WINAPI CServiceModule::_Handler( DWORD dwOpcode )
  193. {
  194. // Not implemented.
  195. }
  196. DWORD WINAPI CServiceModule::_Monitor( void* pv )
  197. {
  198. ((CServiceModule*)pv)->MonitorShutdown();
  199. return 0;
  200. }