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.

1007 lines
32 KiB

  1. /*++
  2. Module Name:
  3. hsmservr.cpp
  4. Abstract:
  5. Provides the Service and main executable implementation.
  6. Author:
  7. Ran Kalach [rankala]
  8. Revision History:
  9. --*/
  10. // Note: Proxy/Stub Information
  11. // To build a separate proxy/stub DLL,
  12. // run nmake -f hsmservrps.mk in the project directory.
  13. #include "stdafx.h"
  14. #include "resource.h"
  15. #include "engcommn.h"
  16. // This include is here due to a MIDL bug - it should have been in the created file hsmservr.h
  17. #include "fsalib.h"
  18. #include "hsmservr.h"
  19. #include <stdio.h>
  20. #include "hsmconpt.h"
  21. // Service dependencies for the HSM server service
  22. #define ENG_DEPENDENCIES L"EventLog\0RpcSs\0Schedule\0NtmsSvc\0\0"
  23. // Service name
  24. #define SERVICE_LOGICAL_NAME _T("Remote_Storage_Server")
  25. #define SERVICE_DISPLAY_NAME L"Remote Storage Server"
  26. CServiceModule _Module;
  27. BEGIN_OBJECT_MAP(ObjectMap)
  28. OBJECT_ENTRY(CLSID_HsmConnPoint, CHsmConnPoint)
  29. END_OBJECT_MAP()
  30. // The global server objects
  31. IHsmServer *g_pEngServer;
  32. IFsaServer *g_pFsaServer;
  33. BOOL g_bEngCreated = FALSE;
  34. BOOL g_bEngInitialized = FALSE;
  35. BOOL g_bFsaCreated = FALSE;
  36. BOOL g_bFsaInitialized = FALSE;
  37. CRITICAL_SECTION g_FsaCriticalSection;
  38. CRITICAL_SECTION g_EngCriticalSection;
  39. #define HSM_SERVER_TRACE_FILE_NAME OLESTR("rsserv.trc")
  40. CComPtr<IWsbTrace> g_pTrace;
  41. // Global functions for console handling
  42. static void ConsoleApp(void);
  43. BOOL WINAPI ConsoleHandler(DWORD dwCtrlType);
  44. static void DebugRelease (void);
  45. // Although some of these functions are big they are declared inline since they are only used once
  46. inline HRESULT CServiceModule::RegisterServer(BOOL bRegTypeLib)
  47. {
  48. WsbTraceIn ( L"CServiceModule::RegisterServer", L"bRegTypeLib = %ls", WsbBoolAsString ( bRegTypeLib ) );
  49. HRESULT hr = S_OK;
  50. try {
  51. WsbAssertHr ( CoInitialize ( NULL ) );
  52. //
  53. // Do not try to remove any previous service since this can cause a delay
  54. // in the registration to happen when another process is trying to get
  55. // this program to self register
  56. //
  57. //
  58. // Add service entries
  59. //
  60. WsbAssertHr( UpdateRegistryFromResource( IDR_Hsmservr, TRUE ) );
  61. //
  62. // Create service
  63. //
  64. WsbAssert( Install(), E_FAIL ) ;
  65. //
  66. // Add object entries
  67. //
  68. WsbAssertHr ( CComModule::RegisterServer( bRegTypeLib ) );
  69. CoUninitialize();
  70. }WsbCatch ( hr )
  71. WsbTraceOut ( L"CServiceModule::RegisterServer", L"HRESULT = %ls", WsbHrAsString ( hr ) );
  72. return( hr );
  73. }
  74. inline HRESULT CServiceModule::UnregisterServer()
  75. {
  76. HRESULT hr = CoInitialize(NULL);
  77. if (FAILED(hr))
  78. return hr;
  79. // Remove service entries
  80. UpdateRegistryFromResource(IDR_Hsmservr, FALSE);
  81. // Remove service
  82. Uninstall();
  83. // Remove object entries
  84. CComModule::UnregisterServer();
  85. CoUninitialize();
  86. return S_OK;
  87. }
  88. inline void CServiceModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h)
  89. {
  90. WsbTraceIn ( L"CServiceModule::Init", L"" );
  91. CComModule::Init(p, h);
  92. m_bService = TRUE;
  93. _tcscpy(m_szServiceName, SERVICE_LOGICAL_NAME);
  94. // set up the initial service status
  95. m_hServiceStatus = NULL;
  96. m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  97. m_status.dwCurrentState = SERVICE_STOPPED;
  98. m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN |
  99. SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_PAUSE_CONTINUE;
  100. m_status.dwWin32ExitCode = 0;
  101. m_status.dwServiceSpecificExitCode = 0;
  102. m_status.dwCheckPoint = 0;
  103. m_status.dwWaitHint = 0;
  104. WsbTraceOut ( L"CServiceModule::Init", L"" );
  105. }
  106. LONG CServiceModule::Unlock()
  107. {
  108. LONG l = CComModule::Unlock();
  109. /* This line put in comment since it causes the process to immediately exit
  110. if (l == 0 && !m_bService)
  111. PostThreadMessage(dwThreadID, WM_QUIT, 0, 0); */
  112. return l;
  113. }
  114. BOOL CServiceModule::IsInstalled()
  115. {
  116. BOOL bResult = FALSE;
  117. SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  118. if (hSCM != NULL) {
  119. SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_QUERY_CONFIG);
  120. if (hService != NULL) {
  121. bResult = TRUE;
  122. ::CloseServiceHandle(hService);
  123. }
  124. ::CloseServiceHandle(hSCM);
  125. }
  126. return bResult;
  127. }
  128. inline BOOL CServiceModule::Install()
  129. /*++
  130. Routine Description:
  131. Install service module.
  132. Arguments:
  133. None.
  134. Return Value:
  135. TRUE - Service installed successfully
  136. FALSE - Service install failed
  137. --*/
  138. {
  139. BOOL bResult = FALSE;
  140. CWsbStringPtr errorMessage;
  141. CWsbStringPtr displayName;
  142. CWsbStringPtr description;
  143. if (!IsInstalled()) {
  144. displayName = SERVICE_DISPLAY_NAME;
  145. description.LoadFromRsc(_Module.m_hInst, IDS_SERVICE_DESCRIPTION );
  146. SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  147. if (hSCM) {
  148. // Get the executable file path
  149. TCHAR szFilePath[_MAX_PATH+1];
  150. ::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
  151. SC_HANDLE hService = ::CreateService(
  152. hSCM, m_szServiceName, (OLECHAR *) displayName,
  153. SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
  154. SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
  155. szFilePath, NULL, NULL, ENG_DEPENDENCIES, NULL, NULL);
  156. if (hService) {
  157. // the service was successfully installed.
  158. bResult = TRUE;
  159. SERVICE_DESCRIPTION svcDesc;
  160. svcDesc.lpDescription = description;
  161. ::ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &svcDesc);
  162. ::CloseServiceHandle(hService);
  163. ::CloseServiceHandle(hSCM);
  164. } else {
  165. errorMessage = WsbHrAsString(HRESULT_FROM_WIN32( GetLastError() ) );
  166. ::CloseServiceHandle(hSCM);
  167. MessageBox(NULL, errorMessage, (OLECHAR *) displayName, MB_OK);
  168. }
  169. } else {
  170. MessageBox(NULL, WsbHrAsString(HRESULT_FROM_WIN32( GetLastError() ) ), (OLECHAR *) displayName, MB_OK);
  171. }
  172. } else {
  173. // service already install, just return TRUE.
  174. bResult = TRUE;
  175. }
  176. return bResult;
  177. }
  178. inline BOOL CServiceModule::Uninstall()
  179. /*++
  180. Routine Description:
  181. Uninstall service module.
  182. Arguments:
  183. None.
  184. Return Value:
  185. TRUE - Service successfully uninstalled.
  186. FALSE - Unable to uninstall service.
  187. --*/
  188. {
  189. BOOL bResult = FALSE;
  190. CWsbStringPtr errorMessage;
  191. CWsbStringPtr displayName;
  192. if (IsInstalled()) {
  193. displayName = SERVICE_DISPLAY_NAME;
  194. SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  195. if (hSCM) {
  196. SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, DELETE);
  197. if (hService) {
  198. BOOL bDelete = ::DeleteService(hService);
  199. // if it did not delete then get the error message
  200. if (!bDelete)
  201. errorMessage = WsbHrAsString(HRESULT_FROM_WIN32( GetLastError() ) );
  202. ::CloseServiceHandle(hService);
  203. ::CloseServiceHandle(hSCM);
  204. if (bDelete) {
  205. // the service was deleted.
  206. bResult = TRUE;
  207. } else {
  208. MessageBox(NULL, errorMessage, (OLECHAR *) displayName, MB_OK);
  209. }
  210. } else {
  211. errorMessage = WsbHrAsString(HRESULT_FROM_WIN32( GetLastError() ) );
  212. ::CloseServiceHandle(hSCM);
  213. MessageBox(NULL, errorMessage, (OLECHAR *) displayName, MB_OK);
  214. }
  215. } else {
  216. MessageBox(NULL, WsbHrAsString(HRESULT_FROM_WIN32( GetLastError() ) ), (OLECHAR *) displayName, MB_OK);
  217. }
  218. } else {
  219. // service not installed, just return TRUE.
  220. bResult = TRUE;
  221. }
  222. return bResult;
  223. }
  224. ///////////////////////////////////////////////////////////////////////////////////////
  225. // Logging functions
  226. //
  227. void
  228. CServiceModule::LogEvent(
  229. DWORD eventId,
  230. ...
  231. )
  232. /*++
  233. Routine Description:
  234. Log data to event log.
  235. Arguments:
  236. eventId - The message Id to log.
  237. Inserts - Message inserts that are merged with the message description specified by
  238. eventId. The number of inserts must match the number specified by the
  239. message description. The last insert must be NULL to indicate the
  240. end of the insert list.
  241. Return Value:
  242. None.
  243. --*/
  244. {
  245. if (m_bService) {
  246. // Report the event.
  247. va_list vaList;
  248. va_start(vaList, eventId);
  249. WsbLogEventV( eventId, 0, NULL, &vaList );
  250. va_end(vaList);
  251. } else {
  252. // Just write the error to the console, if we're not running as a service.
  253. va_list vaList;
  254. const OLECHAR * facilityName = 0;
  255. OLECHAR * messageText = 0;
  256. switch ( HRESULT_FACILITY( eventId ) ) {
  257. case WSB_FACILITY_PLATFORM:
  258. case WSB_FACILITY_RMS:
  259. case WSB_FACILITY_HSMENG:
  260. case WSB_FACILITY_JOB:
  261. case WSB_FACILITY_HSMTSKMGR:
  262. case WSB_FACILITY_FSA:
  263. case WSB_FACILITY_GUI:
  264. case WSB_FACILITY_MOVER:
  265. case WSB_FACILITY_LAUNCH:
  266. facilityName = WSB_FACILITY_PLATFORM_NAME;
  267. break;
  268. }
  269. if ( facilityName ) {
  270. // Print out the variable arguments
  271. // NOTE: Positional parameters in the inserts are not processed. These
  272. // are done by ReportEvent() only.
  273. HMODULE hLib = LoadLibraryEx( facilityName, NULL, LOAD_LIBRARY_AS_DATAFILE );
  274. if (hLib != NULL) {
  275. va_start(vaList, eventId);
  276. FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  277. hLib,
  278. eventId,
  279. MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ),
  280. (LPTSTR) &messageText,
  281. 0,
  282. &vaList );
  283. va_end(vaList);
  284. FreeLibrary(hLib);
  285. }
  286. if ( messageText ) {
  287. _putts(messageText);
  288. LocalFree( messageText );
  289. } else {
  290. _tprintf( OLESTR("!!!!! ERROR !!!!! - Message <0x%08x> could not be translated.\n"), eventId );
  291. }
  292. } else {
  293. _tprintf( OLESTR("!!!!! ERROR !!!!! - Message File for <0x%08x> could not be found.\n"), eventId );
  294. }
  295. }
  296. }
  297. //////////////////////////////////////////////////////////////////////////////////////////////
  298. // Service startup and registration
  299. inline void CServiceModule::Start()
  300. {
  301. SERVICE_TABLE_ENTRY st[] =
  302. {
  303. { m_szServiceName, _ServiceMain},
  304. { NULL, NULL}
  305. };
  306. if (!::StartServiceCtrlDispatcher(st)) {
  307. m_bService = FALSE;
  308. m_status.dwWin32ExitCode = GetLastError();
  309. }
  310. }
  311. inline void CServiceModule::ServiceMain(DWORD /* dwArgc */, LPTSTR* /* lpszArgv */)
  312. {
  313. SetServiceStatus(SERVICE_START_PENDING);
  314. // Register the control request handler
  315. m_status.dwCurrentState = SERVICE_START_PENDING;
  316. m_hServiceStatus = RegisterServiceCtrlHandlerEx(m_szServiceName, _HandlerEx,
  317. NULL);
  318. if (m_hServiceStatus == NULL) {
  319. LogEvent( HSM_MESSAGE_SERVICE_HANDLER_NOT_INSTALLED, NULL );
  320. return;
  321. }
  322. m_status.dwWin32ExitCode = S_OK;
  323. m_status.dwCheckPoint = 0;
  324. m_status.dwWaitHint = 0;
  325. // When the Run function returns, the service has stopped.
  326. Run();
  327. SetServiceStatus(SERVICE_STOPPED);
  328. LogEvent( HSM_MESSAGE_SERVICE_STOPPED, NULL );
  329. }
  330. inline DWORD CServiceModule::HandlerEx(DWORD dwOpcode, DWORD fdwEventType,
  331. LPVOID /* lpEventData */, LPVOID /* lpContext */)
  332. {
  333. DWORD dwRetCode = 0;
  334. HRESULT hr = S_OK;
  335. HRESULT hr1 = S_OK;
  336. HSM_SYSTEM_STATE SysState;
  337. WsbTraceIn(OLESTR("CServiceModule::HandlerEx"), OLESTR("opCode=%lx"),
  338. dwOpcode );
  339. switch (dwOpcode) {
  340. case SERVICE_CONTROL_STOP: {
  341. SetServiceStatus(SERVICE_STOP_PENDING);
  342. PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
  343. }
  344. break;
  345. case SERVICE_CONTROL_PAUSE:
  346. SetServiceStatus(SERVICE_PAUSE_PENDING);
  347. SysState.State = HSM_STATE_SUSPEND;
  348. if (g_pEngServer && g_bEngInitialized) {
  349. g_pEngServer->ChangeSysState(&SysState);
  350. }
  351. if (g_pFsaServer && g_bFsaInitialized) {
  352. g_pFsaServer->ChangeSysState(&SysState);
  353. }
  354. SetServiceStatus(SERVICE_PAUSED);
  355. break;
  356. case SERVICE_CONTROL_CONTINUE:
  357. SetServiceStatus(SERVICE_CONTINUE_PENDING);
  358. SysState.State = HSM_STATE_RESUME;
  359. if (g_pFsaServer && g_bFsaInitialized) {
  360. g_pFsaServer->ChangeSysState(&SysState);
  361. }
  362. if (g_pEngServer && g_bEngInitialized) {
  363. g_pEngServer->ChangeSysState(&SysState);
  364. }
  365. SetServiceStatus(SERVICE_RUNNING);
  366. break;
  367. case SERVICE_CONTROL_INTERROGATE:
  368. break;
  369. case SERVICE_CONTROL_SHUTDOWN:
  370. // Prepare Eng server for releasing
  371. if (g_pEngServer && g_bEngInitialized) {
  372. SysState.State = HSM_STATE_SHUTDOWN;
  373. if (!SUCCEEDED(hr = g_pEngServer->ChangeSysState(&SysState))) {
  374. LogEvent( HSM_MESSAGE_SERVICE_FAILED_TO_SHUTDOWN, WsbHrAsString(hr), NULL );
  375. }
  376. }
  377. // Prepare Fsa server for releasing
  378. if (g_pFsaServer && g_bFsaInitialized) {
  379. CComPtr<IWsbServer> pWsbServer;
  380. SysState.State = HSM_STATE_SHUTDOWN;
  381. // If it was initialized, then we should try to save the current state.
  382. hr = g_pFsaServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer);
  383. if (hr == S_OK) {
  384. hr = pWsbServer->SaveAll();
  385. }
  386. if (FAILED(hr)) {
  387. LogEvent(FSA_MESSAGE_SERVICE_FAILED_TO_SAVE_DATABASE, WsbHrAsString(hr), NULL );
  388. }
  389. hr = g_pFsaServer->ChangeSysState(&SysState);
  390. if (FAILED(hr)) {
  391. LogEvent( FSA_MESSAGE_SERVICE_FAILED_TO_SHUTDOWN, WsbHrAsString(hr), NULL );
  392. }
  393. }
  394. // Release Eng server
  395. if (g_bEngCreated && (g_pEngServer != 0)) {
  396. // Free server inside a crit. section thus avoid conflicts with accessing clients
  397. EnterCriticalSection(&g_EngCriticalSection);
  398. g_bEngInitialized = FALSE;
  399. g_bEngCreated = FALSE;
  400. // Disconnect all remote clients
  401. (void)CoDisconnectObject(g_pEngServer, 0);
  402. // Forse object destroy, ignore reference count here
  403. IWsbServer *pWsbServer;
  404. hr = g_pEngServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer);
  405. if (hr == S_OK) {
  406. pWsbServer->Release();
  407. pWsbServer->DestroyObject();
  408. }
  409. g_pEngServer = 0;
  410. LeaveCriticalSection (&g_EngCriticalSection);
  411. }
  412. // Release Fsa server
  413. if (g_bFsaCreated && (g_pFsaServer != 0)) {
  414. // Free server inside a crit. section thus avoid conflicts with accessing clients
  415. EnterCriticalSection(&g_FsaCriticalSection);
  416. g_bFsaInitialized = FALSE;
  417. g_bFsaCreated = FALSE;
  418. // Disconnect all remote clients
  419. (void)CoDisconnectObject(g_pFsaServer, 0);
  420. // Forse object destroy, ignore reference count here
  421. IWsbServer *pWsbServer;
  422. hr = g_pFsaServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer);
  423. if (hr == S_OK) {
  424. pWsbServer->Release();
  425. pWsbServer->DestroyObject();
  426. }
  427. g_pFsaServer = 0;
  428. LeaveCriticalSection(&g_FsaCriticalSection);
  429. }
  430. break;
  431. case SERVICE_CONTROL_POWEREVENT:
  432. if (S_OK == WsbPowerEventNtToHsm(fdwEventType, &SysState.State)) {
  433. WsbTrace(OLESTR("CServiceModule::HandlerEx: power event, fdwEventType = %lx\n"),
  434. fdwEventType);
  435. if (g_pEngServer && g_bEngInitialized) {
  436. hr = g_pEngServer->ChangeSysState(&SysState);
  437. }
  438. if (g_pFsaServer && g_bFsaInitialized) {
  439. hr1 = g_pFsaServer->ChangeSysState(&SysState);
  440. }
  441. if ((S_FALSE == hr) || (S_FALSE == hr1)) {
  442. dwRetCode = BROADCAST_QUERY_DENY;
  443. }
  444. }
  445. break;
  446. default:
  447. LogEvent( HSM_MESSAGE_SERVICE_RECEIVED_BAD_REQUEST, NULL );
  448. }
  449. WsbTraceOut(OLESTR("CServiceModule::HandlerEx"), OLESTR("dwRetCode = %lx"),
  450. dwRetCode );
  451. return(dwRetCode);
  452. }
  453. void WINAPI CServiceModule::_ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
  454. {
  455. _Module.ServiceMain(dwArgc, lpszArgv);
  456. }
  457. DWORD WINAPI CServiceModule::_HandlerEx(DWORD dwOpcode, DWORD fdwEventType,
  458. LPVOID lpEventData, LPVOID lpContext)
  459. {
  460. return(_Module.HandlerEx(dwOpcode, fdwEventType, lpEventData, lpContext));
  461. }
  462. void CServiceModule::SetServiceStatus(DWORD dwState)
  463. {
  464. m_status.dwCurrentState = dwState;
  465. ::SetServiceStatus(m_hServiceStatus, &m_status);
  466. }
  467. void CServiceModule::Run()
  468. {
  469. HRESULT hr = S_OK;
  470. try {
  471. // Initialize both servers critical section.
  472. if (! InitializeCriticalSectionAndSpinCount (&g_FsaCriticalSection, 1000)) {
  473. m_status.dwWin32ExitCode = GetLastError();
  474. hr = HRESULT_FROM_WIN32(m_status.dwWin32ExitCode);
  475. LogEvent( HSM_MESSAGE_SERVICE_INITIALIZATION_FAILED, WsbHrAsString(hr), NULL );
  476. return;
  477. }
  478. if (! InitializeCriticalSectionAndSpinCount (&g_EngCriticalSection, 1000)) {
  479. m_status.dwWin32ExitCode = GetLastError();
  480. hr = HRESULT_FROM_WIN32(m_status.dwWin32ExitCode);
  481. LogEvent( HSM_MESSAGE_SERVICE_INITIALIZATION_FAILED, WsbHrAsString(hr), NULL );
  482. DeleteCriticalSection(&g_FsaCriticalSection);
  483. return;
  484. }
  485. _Module.dwThreadID = GetCurrentThreadId();
  486. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  487. _ASSERTE(SUCCEEDED(hr));
  488. if (hr != S_OK) {
  489. m_status.dwWin32ExitCode = HRESULT_CODE(hr) ;
  490. LogEvent( HSM_MESSAGE_SERVICE_FAILED_COM_INIT, OLESTR("CoInitializeEx"),
  491. WsbHrAsString(hr), NULL );
  492. DeleteCriticalSection(&g_EngCriticalSection);
  493. DeleteCriticalSection(&g_FsaCriticalSection);
  494. return;
  495. }
  496. // This provides Admin only access.
  497. CWsbSecurityDescriptor sd;
  498. sd.InitializeFromThreadToken();
  499. WsbAffirmHr(sd.AllowRid( SECURITY_LOCAL_SYSTEM_RID, COM_RIGHTS_EXECUTE ));
  500. WsbAffirmHr(sd.AllowRid( DOMAIN_ALIAS_RID_ADMINS, COM_RIGHTS_EXECUTE ));
  501. hr = CoInitializeSecurity(sd, -1, NULL, NULL,
  502. RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL);
  503. _ASSERTE(SUCCEEDED(hr));
  504. if (hr != S_OK) {
  505. m_status.dwWin32ExitCode = HRESULT_CODE(hr) ;
  506. LogEvent( HSM_MESSAGE_SERVICE_FAILED_COM_INIT, OLESTR("CoInitializeSecurity"),
  507. WsbHrAsString(hr), NULL );
  508. CoUninitialize();
  509. DeleteCriticalSection(&g_EngCriticalSection);
  510. DeleteCriticalSection(&g_FsaCriticalSection);
  511. return;
  512. }
  513. // Create the trace object and initialize it
  514. hr = CoCreateInstance(CLSID_CWsbTrace, 0, CLSCTX_SERVER, IID_IWsbTrace, (void **) &g_pTrace);
  515. _ASSERTE(SUCCEEDED(hr));
  516. if (hr != S_OK) {
  517. m_status.dwWin32ExitCode = HRESULT_CODE(hr) ;
  518. LogEvent( HSM_MESSAGE_SERVICE_INITIALIZATION_FAILED, WsbHrAsString(hr), NULL );
  519. CoUninitialize();
  520. DeleteCriticalSection(&g_EngCriticalSection);
  521. DeleteCriticalSection(&g_FsaCriticalSection);
  522. return;
  523. }
  524. // Figure out where to store information and initialize trace.
  525. // Currently, Engine & Fsa share the same trace file
  526. WsbGetServiceTraceDefaults(m_szServiceName, HSM_SERVER_TRACE_FILE_NAME, g_pTrace);
  527. WsbTraceIn(OLESTR("CServiceModule::Run"), OLESTR(""));
  528. hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE);
  529. if (hr != S_OK) {
  530. m_status.dwWin32ExitCode = HRESULT_CODE(hr) ;
  531. LogEvent( HSM_MESSAGE_SERVICE_FAILED_COM_INIT, OLESTR("CoRegisterClassObjects"),
  532. WsbHrAsString(hr), NULL );
  533. g_pTrace = 0;
  534. CoUninitialize();
  535. DeleteCriticalSection(&g_EngCriticalSection);
  536. DeleteCriticalSection(&g_FsaCriticalSection);
  537. return;
  538. }
  539. // Now we need to get the HSM Server initialized
  540. // First Fsa server is initialized, ONLY if it succeeds, Engine
  541. // server is initialized as well
  542. m_status.dwCheckPoint = 1;
  543. m_status.dwWaitHint = 60000;
  544. SetServiceStatus(SERVICE_START_PENDING);
  545. // initialize Fsa server
  546. if (! g_pFsaServer) {
  547. try {
  548. //
  549. // Create and initialize the server.
  550. //
  551. WsbAffirmHr( CoCreateInstance(CLSID_CFsaServerNTFS, 0, CLSCTX_SERVER, IID_IFsaServer, (void**) &g_pFsaServer) );
  552. // Created the server, now initialize it
  553. g_bFsaCreated = TRUE;
  554. CComPtr<IWsbServer> pWsbServer;
  555. WsbAffirmHr(g_pFsaServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer));
  556. WsbAffirmHrOk(pWsbServer->SetTrace(g_pTrace));
  557. hr = g_pFsaServer->Init();
  558. WsbAffirmHrOk(hr);
  559. g_bFsaInitialized = TRUE;
  560. }WsbCatchAndDo( hr,
  561. // If the error is a Win32 make it back to a Win32 error else send
  562. // the HR in the service specific exit code
  563. if ( FACILITY_WIN32 == HRESULT_FACILITY(hr) ){
  564. m_status.dwWin32ExitCode = HRESULT_CODE(hr) ;}else{
  565. m_status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
  566. m_status.dwServiceSpecificExitCode = hr ;}
  567. LogEvent( FSA_MESSAGE_SERVICE_INITIALIZATION_FAILED , WsbHrAsString(hr), NULL );
  568. );
  569. }
  570. WsbTrace (OLESTR("Fsa: Created=%ls , Initialized=%ls\n"),
  571. WsbBoolAsString(g_bFsaCreated), WsbBoolAsString(g_bFsaInitialized));
  572. // initialize Engine server
  573. if ((! g_pEngServer) && (hr == S_OK)) {
  574. try {
  575. //
  576. // Create and initialize the server.
  577. //
  578. WsbAffirmHr( CoCreateInstance( CLSID_HsmServer, 0, CLSCTX_SERVER, IID_IHsmServer, (void **)&g_pEngServer ) );
  579. g_bEngCreated = TRUE;
  580. CComPtr<IWsbServer> pWsbServer;
  581. WsbAffirmHr(g_pEngServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer));
  582. WsbAffirmHrOk(pWsbServer->SetTrace(g_pTrace));
  583. WsbAffirmHr(g_pEngServer->Init());
  584. g_bEngInitialized = TRUE;
  585. }WsbCatchAndDo(hr,
  586. // If the error is a Win32 make it back to a Win32 error else send
  587. // the HR in the service specific exit code
  588. if ( FACILITY_WIN32 == HRESULT_FACILITY(hr) ){
  589. m_status.dwWin32ExitCode = HRESULT_CODE(hr) ;}else{
  590. m_status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
  591. m_status.dwServiceSpecificExitCode = hr ;}
  592. LogEvent( HSM_MESSAGE_SERVICE_CREATE_FAILED, WsbHrAsString(hr), NULL );
  593. );
  594. }
  595. WsbTrace (OLESTR("Engine: Created=%ls , Initialized=%ls\n"),
  596. WsbBoolAsString(g_bEngCreated), WsbBoolAsString(g_bEngInitialized));
  597. if (hr == S_OK) {
  598. SetServiceStatus(SERVICE_RUNNING);
  599. LogEvent( HSM_MESSAGE_SERVICE_STARTED, NULL );
  600. MSG msg;
  601. while (GetMessage(&msg, 0, 0, 0)) {
  602. // If something has changed with the devices, then rescan. At somepoint we
  603. // may want to do a more limited scan (i.e. just update what changed), but this
  604. // should cover it for now.
  605. //
  606. // Since something has changed, we will also force a rewrite of the persistant data.
  607. if (WM_DEVICECHANGE == msg.message) {
  608. CComPtr<IWsbServer> pWsbServer;
  609. try {
  610. WsbAffirmHr(g_pFsaServer->ScanForResources());
  611. WsbAffirmHr(g_pFsaServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer));
  612. WsbAffirmHr(pWsbServer->SaveAll());
  613. }WsbCatchAndDo(hr,
  614. // If we had a problem then log a message and exit the service. We don't
  615. // want to leave the service running, since we might have invalid drive
  616. // mappings.
  617. LogEvent(FSA_MESSAGE_RESCANFAILED, WsbHrAsString(hr), NULL);
  618. PostMessage(NULL, WM_QUIT, 0, 0);
  619. );
  620. pWsbServer = 0;
  621. }
  622. DispatchMessage(&msg);
  623. }
  624. }
  625. LogEvent( HSM_MESSAGE_SERVICE_EXITING, NULL );
  626. // TEMPORARY - call a function so we can break before release.
  627. DebugRelease ();
  628. // prepare for releasing Eng server
  629. if ((g_pEngServer != 0) && g_bEngCreated && g_bEngInitialized) {
  630. // Save out server data
  631. HSM_SYSTEM_STATE SysState;
  632. SysState.State = HSM_STATE_SHUTDOWN;
  633. hr = g_pEngServer->ChangeSysState(&SysState);
  634. if (FAILED(hr)) {
  635. LogEvent( HSM_MESSAGE_SERVICE_FAILED_TO_SHUTDOWN, WsbHrAsString(hr), NULL );
  636. }
  637. }
  638. // Prepare for releasing Fsa server
  639. if ((g_pFsaServer != 0) && g_bFsaCreated && g_bFsaInitialized) {
  640. CComPtr<IWsbServer> pWsbServer;
  641. HSM_SYSTEM_STATE SysState;
  642. hr = g_pFsaServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer);
  643. if (hr == S_OK) {
  644. hr = pWsbServer->SaveAll();
  645. }
  646. if (FAILED(hr)) {
  647. LogEvent( FSA_MESSAGE_SERVICE_FAILED_TO_SAVE_DATABASE, WsbHrAsString(hr), NULL );
  648. }
  649. pWsbServer = 0;
  650. // Persist the databases and release everything
  651. SysState.State = HSM_STATE_SHUTDOWN;
  652. hr = g_pFsaServer->ChangeSysState(&SysState);
  653. if (FAILED(hr)) {
  654. LogEvent( FSA_MESSAGE_SERVICE_FAILED_TO_SHUTDOWN, WsbHrAsString(hr), NULL );
  655. }
  656. }
  657. // Release Eng server
  658. if (g_bEngCreated && (g_pEngServer != 0)) {
  659. // Free server inside a crit. section thus avoid conflicts with accessing clients
  660. EnterCriticalSection(&g_EngCriticalSection);
  661. g_bEngInitialized = FALSE;
  662. g_bEngCreated = FALSE;
  663. // Disconnect all remote clients
  664. (void)CoDisconnectObject(g_pEngServer, 0);
  665. // Forse object destroy, ignore reference count here
  666. IWsbServer *pWsbServer;
  667. hr = g_pEngServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer);
  668. if (hr == S_OK) {
  669. pWsbServer->Release();
  670. pWsbServer->DestroyObject();
  671. }
  672. g_pEngServer = 0;
  673. LeaveCriticalSection (&g_EngCriticalSection);
  674. }
  675. // Release Fsa server
  676. if (g_bFsaCreated && (g_pFsaServer != 0)) {
  677. // Free server inside a crit. section thus avoid conflicts with accessing clients
  678. EnterCriticalSection(&g_FsaCriticalSection);
  679. g_bFsaInitialized = FALSE;
  680. g_bFsaCreated = FALSE;
  681. // Disconnect all remote clients
  682. (void)CoDisconnectObject(g_pFsaServer, 0);
  683. // Forse object destroy, ignore reference count here
  684. IWsbServer *pWsbServer;
  685. hr = g_pFsaServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer);
  686. if (hr == S_OK) {
  687. pWsbServer->Release();
  688. pWsbServer->DestroyObject();
  689. }
  690. g_pFsaServer = 0;
  691. LeaveCriticalSection(&g_FsaCriticalSection);
  692. }
  693. _Module.RevokeClassObjects();
  694. WsbTraceOut(OLESTR("CServiceModule::Run"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  695. g_pTrace = 0;
  696. CoUninitialize();
  697. // Delete the server critical section
  698. DeleteCriticalSection(&g_EngCriticalSection);
  699. DeleteCriticalSection(&g_FsaCriticalSection);
  700. }WsbCatch(hr);
  701. }
  702. //
  703. // Tries to start the service as a console application
  704. // (not through SCM calls)
  705. //
  706. static void ConsoleApp()
  707. {
  708. HRESULT hr;
  709. ::SetConsoleCtrlHandler(ConsoleHandler, TRUE) ;
  710. // set Registry for process
  711. hr = CoInitialize (NULL);
  712. if (SUCCEEDED(hr)) {
  713. hr = _Module.UpdateRegistryFromResourceD(IDR_Serv2Proc, TRUE);
  714. CoUninitialize();
  715. _Module.Run();
  716. //
  717. // set Registry back for service
  718. hr = CoInitialize (NULL);
  719. if (SUCCEEDED(hr)) {
  720. hr = _Module.UpdateRegistryFromResourceD(IDR_Proc2Serv, TRUE);
  721. CoUninitialize();
  722. }
  723. }
  724. }
  725. //
  726. // Callback function for handling console events
  727. //
  728. BOOL WINAPI ConsoleHandler(DWORD dwCtrlType)
  729. {
  730. switch (dwCtrlType) {
  731. case CTRL_BREAK_EVENT:
  732. case CTRL_C_EVENT:
  733. case CTRL_CLOSE_EVENT:
  734. case CTRL_LOGOFF_EVENT:
  735. case CTRL_SHUTDOWN_EVENT:
  736. PostThreadMessage(_Module.dwThreadID, WM_QUIT, 0, 0);
  737. return TRUE;
  738. }
  739. return FALSE ;
  740. }
  741. /////////////////////////////////////////////////////////////////////////////
  742. //
  743. extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
  744. HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
  745. {
  746. _Module.Init(ObjectMap, hInstance);
  747. TCHAR szTokens[] = _T("-/");
  748. LPTSTR lpszToken = _tcstok(lpCmdLine, szTokens);
  749. while (lpszToken != NULL) {
  750. if (_tcsicmp(lpszToken, _T("UnregServer"))==0) {
  751. return _Module.UnregisterServer();
  752. }
  753. if (_tcsicmp(lpszToken, _T("RegServer"))==0) {
  754. return _Module.RegisterServer(FALSE);
  755. }
  756. #ifdef DBG
  757. if (_tcsicmp(lpszToken, _T("D"))==0) {
  758. _Module.m_bService = FALSE;
  759. }
  760. #endif
  761. lpszToken = _tcstok(NULL, szTokens);
  762. }
  763. //
  764. // Cheap hack to force the ESE.DLL to be loaded before any other threads are started
  765. //
  766. LoadLibrary( L"RsIdb.dll" );
  767. if (_Module.m_bService) {
  768. _Module.Start();
  769. } else {
  770. ConsoleApp ();
  771. }
  772. // When we get here, the service has been stopped
  773. return _Module.m_status.dwWin32ExitCode;
  774. }
  775. void DebugRelease ()
  776. {
  777. WsbTrace(OLESTR("DebugRelease in"));
  778. WsbTrace(OLESTR("DebugRelease out"));
  779. }