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.

1008 lines
31 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];
  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. if (GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
  309. Run();
  310. }
  311. }
  312. inline void CServiceModule::ServiceMain(DWORD /* dwArgc */, LPTSTR* /* lpszArgv */)
  313. {
  314. SetServiceStatus(SERVICE_START_PENDING);
  315. // Register the control request handler
  316. m_status.dwCurrentState = SERVICE_START_PENDING;
  317. m_hServiceStatus = RegisterServiceCtrlHandlerEx(m_szServiceName, _HandlerEx,
  318. NULL);
  319. if (m_hServiceStatus == NULL) {
  320. LogEvent( HSM_MESSAGE_SERVICE_HANDLER_NOT_INSTALLED, NULL );
  321. return;
  322. }
  323. m_status.dwWin32ExitCode = S_OK;
  324. m_status.dwCheckPoint = 0;
  325. m_status.dwWaitHint = 0;
  326. // When the Run function returns, the service has stopped.
  327. Run();
  328. SetServiceStatus(SERVICE_STOPPED);
  329. LogEvent( HSM_MESSAGE_SERVICE_STOPPED, NULL );
  330. }
  331. inline DWORD CServiceModule::HandlerEx(DWORD dwOpcode, DWORD fdwEventType,
  332. LPVOID /* lpEventData */, LPVOID /* lpContext */)
  333. {
  334. DWORD dwRetCode = 0;
  335. HRESULT hr = S_OK;
  336. HRESULT hr1 = S_OK;
  337. HSM_SYSTEM_STATE SysState;
  338. WsbTraceIn(OLESTR("CServiceModule::HandlerEx"), OLESTR("opCode=%lx"),
  339. dwOpcode );
  340. switch (dwOpcode) {
  341. case SERVICE_CONTROL_STOP: {
  342. SetServiceStatus(SERVICE_STOP_PENDING);
  343. PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
  344. }
  345. break;
  346. case SERVICE_CONTROL_PAUSE:
  347. SetServiceStatus(SERVICE_PAUSE_PENDING);
  348. SysState.State = HSM_STATE_SUSPEND;
  349. if (g_pEngServer && g_bEngInitialized) {
  350. g_pEngServer->ChangeSysState(&SysState);
  351. }
  352. if (g_pFsaServer && g_bFsaInitialized) {
  353. g_pFsaServer->ChangeSysState(&SysState);
  354. }
  355. SetServiceStatus(SERVICE_PAUSED);
  356. break;
  357. case SERVICE_CONTROL_CONTINUE:
  358. SetServiceStatus(SERVICE_CONTINUE_PENDING);
  359. SysState.State = HSM_STATE_RESUME;
  360. if (g_pFsaServer && g_bFsaInitialized) {
  361. g_pFsaServer->ChangeSysState(&SysState);
  362. }
  363. if (g_pEngServer && g_bEngInitialized) {
  364. g_pEngServer->ChangeSysState(&SysState);
  365. }
  366. SetServiceStatus(SERVICE_RUNNING);
  367. break;
  368. case SERVICE_CONTROL_INTERROGATE:
  369. break;
  370. case SERVICE_CONTROL_SHUTDOWN:
  371. // Prepare Eng server for releasing
  372. if (g_pEngServer && g_bEngInitialized) {
  373. SysState.State = HSM_STATE_SHUTDOWN;
  374. if (!SUCCEEDED(hr = g_pEngServer->ChangeSysState(&SysState))) {
  375. LogEvent( HSM_MESSAGE_SERVICE_FAILED_TO_SHUTDOWN, WsbHrAsString(hr), NULL );
  376. }
  377. }
  378. // Prepare Fsa server for releasing
  379. if (g_pFsaServer && g_bFsaInitialized) {
  380. CComPtr<IWsbServer> pWsbServer;
  381. SysState.State = HSM_STATE_SHUTDOWN;
  382. // If it was initialized, then we should try to save the current state.
  383. hr = g_pFsaServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer);
  384. if (hr == S_OK) {
  385. hr = pWsbServer->SaveAll();
  386. }
  387. if (FAILED(hr)) {
  388. LogEvent(FSA_MESSAGE_SERVICE_FAILED_TO_SAVE_DATABASE, WsbHrAsString(hr), NULL );
  389. }
  390. hr = g_pFsaServer->ChangeSysState(&SysState);
  391. if (FAILED(hr)) {
  392. LogEvent( FSA_MESSAGE_SERVICE_FAILED_TO_SHUTDOWN, WsbHrAsString(hr), NULL );
  393. }
  394. }
  395. // Release Eng server
  396. if (g_bEngCreated && (g_pEngServer != 0)) {
  397. // Free server inside a crit. section thus avoid conflicts with accessing clients
  398. EnterCriticalSection(&g_EngCriticalSection);
  399. g_bEngInitialized = FALSE;
  400. g_bEngCreated = FALSE;
  401. // Disconnect all remote clients
  402. (void)CoDisconnectObject(g_pEngServer, 0);
  403. // Forse object destroy, ignore reference count here
  404. IWsbServer *pWsbServer;
  405. hr = g_pEngServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer);
  406. if (hr == S_OK) {
  407. pWsbServer->Release();
  408. pWsbServer->DestroyObject();
  409. }
  410. g_pEngServer = 0;
  411. LeaveCriticalSection (&g_EngCriticalSection);
  412. }
  413. // Release Fsa server
  414. if (g_bFsaCreated && (g_pFsaServer != 0)) {
  415. // Free server inside a crit. section thus avoid conflicts with accessing clients
  416. EnterCriticalSection(&g_FsaCriticalSection);
  417. g_bFsaInitialized = FALSE;
  418. g_bFsaCreated = FALSE;
  419. // Disconnect all remote clients
  420. (void)CoDisconnectObject(g_pFsaServer, 0);
  421. // Forse object destroy, ignore reference count here
  422. IWsbServer *pWsbServer;
  423. hr = g_pFsaServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer);
  424. if (hr == S_OK) {
  425. pWsbServer->Release();
  426. pWsbServer->DestroyObject();
  427. }
  428. g_pFsaServer = 0;
  429. LeaveCriticalSection(&g_FsaCriticalSection);
  430. }
  431. break;
  432. case SERVICE_CONTROL_POWEREVENT:
  433. if (S_OK == WsbPowerEventNtToHsm(fdwEventType, &SysState.State)) {
  434. WsbTrace(OLESTR("CServiceModule::HandlerEx: power event, fdwEventType = %lx\n"),
  435. fdwEventType);
  436. if (g_pEngServer && g_bEngInitialized) {
  437. hr = g_pEngServer->ChangeSysState(&SysState);
  438. }
  439. if (g_pFsaServer && g_bFsaInitialized) {
  440. hr1 = g_pFsaServer->ChangeSysState(&SysState);
  441. }
  442. if ((S_FALSE == hr) || (S_FALSE == hr1)) {
  443. dwRetCode = BROADCAST_QUERY_DENY;
  444. }
  445. }
  446. break;
  447. default:
  448. LogEvent( HSM_MESSAGE_SERVICE_RECEIVED_BAD_REQUEST, NULL );
  449. }
  450. WsbTraceOut(OLESTR("CServiceModule::HandlerEx"), OLESTR("dwRetCode = %lx"),
  451. dwRetCode );
  452. return(dwRetCode);
  453. }
  454. void WINAPI CServiceModule::_ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
  455. {
  456. _Module.ServiceMain(dwArgc, lpszArgv);
  457. }
  458. DWORD WINAPI CServiceModule::_HandlerEx(DWORD dwOpcode, DWORD fdwEventType,
  459. LPVOID lpEventData, LPVOID lpContext)
  460. {
  461. return(_Module.HandlerEx(dwOpcode, fdwEventType, lpEventData, lpContext));
  462. }
  463. void CServiceModule::SetServiceStatus(DWORD dwState)
  464. {
  465. m_status.dwCurrentState = dwState;
  466. ::SetServiceStatus(m_hServiceStatus, &m_status);
  467. }
  468. void CServiceModule::Run()
  469. {
  470. HRESULT hr = S_OK;
  471. try {
  472. // Initialize both servers critical section.
  473. try {
  474. InitializeCriticalSectionAndSpinCount (&g_FsaCriticalSection, 1000);
  475. InitializeCriticalSectionAndSpinCount (&g_EngCriticalSection, 1000);
  476. } catch (DWORD status) {
  477. WsbLogEvent(status, 0, NULL, NULL);
  478. switch (status) {
  479. case STATUS_NO_MEMORY:
  480. WsbThrow(E_OUTOFMEMORY);
  481. break;
  482. default:
  483. WsbThrow(E_UNEXPECTED);
  484. }
  485. }
  486. _Module.dwThreadID = GetCurrentThreadId();
  487. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  488. _ASSERTE(SUCCEEDED(hr));
  489. if (hr != S_OK) {
  490. m_status.dwWin32ExitCode = HRESULT_CODE(hr) ;
  491. LogEvent( HSM_MESSAGE_SERVICE_FAILED_COM_INIT, OLESTR("CoInitializeEx"),
  492. WsbHrAsString(hr), NULL );
  493. DeleteCriticalSection(&g_EngCriticalSection);
  494. DeleteCriticalSection(&g_FsaCriticalSection);
  495. return;
  496. }
  497. // This provides Admin only access.
  498. CWsbSecurityDescriptor sd;
  499. sd.InitializeFromThreadToken();
  500. sd.AllowRid( SECURITY_LOCAL_SYSTEM_RID, COM_RIGHTS_EXECUTE );
  501. sd.AllowRid( DOMAIN_ALIAS_RID_ADMINS, COM_RIGHTS_EXECUTE );
  502. hr = CoInitializeSecurity(sd, -1, NULL, NULL,
  503. RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
  504. _ASSERTE(SUCCEEDED(hr));
  505. if (hr != S_OK) {
  506. m_status.dwWin32ExitCode = HRESULT_CODE(hr) ;
  507. LogEvent( HSM_MESSAGE_SERVICE_FAILED_COM_INIT, OLESTR("CoInitializeSecurity"),
  508. WsbHrAsString(hr), NULL );
  509. CoUninitialize();
  510. DeleteCriticalSection(&g_EngCriticalSection);
  511. DeleteCriticalSection(&g_FsaCriticalSection);
  512. return;
  513. }
  514. // Create the trace object and initialize it
  515. hr = CoCreateInstance(CLSID_CWsbTrace, 0, CLSCTX_SERVER, IID_IWsbTrace, (void **) &g_pTrace);
  516. _ASSERTE(SUCCEEDED(hr));
  517. if (hr != S_OK) {
  518. m_status.dwWin32ExitCode = HRESULT_CODE(hr) ;
  519. LogEvent( HSM_MESSAGE_SERVICE_INITIALIZATION_FAILED, WsbHrAsString(hr), NULL );
  520. CoUninitialize();
  521. DeleteCriticalSection(&g_EngCriticalSection);
  522. DeleteCriticalSection(&g_FsaCriticalSection);
  523. return;
  524. }
  525. // Figure out where to store information and initialize trace.
  526. // Currently, Engine & Fsa share the same trace file
  527. WsbGetServiceTraceDefaults(m_szServiceName, HSM_SERVER_TRACE_FILE_NAME, g_pTrace);
  528. WsbTraceIn(OLESTR("CServiceModule::Run"), OLESTR(""));
  529. hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE);
  530. if (hr != S_OK) {
  531. m_status.dwWin32ExitCode = HRESULT_CODE(hr) ;
  532. LogEvent( HSM_MESSAGE_SERVICE_FAILED_COM_INIT, OLESTR("CoRegisterClassObjects"),
  533. WsbHrAsString(hr), NULL );
  534. g_pTrace = 0;
  535. CoUninitialize();
  536. DeleteCriticalSection(&g_EngCriticalSection);
  537. DeleteCriticalSection(&g_FsaCriticalSection);
  538. return;
  539. }
  540. // Now we need to get the HSM Server initialized
  541. // First Fsa server is initialized, ONLY if it succeeds, Engine
  542. // server is initialized as well
  543. m_status.dwCheckPoint = 1;
  544. m_status.dwWaitHint = 60000;
  545. SetServiceStatus(SERVICE_START_PENDING);
  546. // initialize Fsa server
  547. if (! g_pFsaServer) {
  548. try {
  549. //
  550. // Create and initialize the server.
  551. //
  552. WsbAffirmHr( CoCreateInstance(CLSID_CFsaServerNTFS, 0, CLSCTX_SERVER, IID_IFsaServer, (void**) &g_pFsaServer) );
  553. // Created the server, now initialize it
  554. g_bFsaCreated = TRUE;
  555. CComPtr<IWsbServer> pWsbServer;
  556. WsbAffirmHr(g_pFsaServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer));
  557. WsbAffirmHrOk(pWsbServer->SetTrace(g_pTrace));
  558. hr = g_pFsaServer->Init();
  559. WsbAffirmHrOk(hr);
  560. g_bFsaInitialized = TRUE;
  561. }WsbCatchAndDo( hr,
  562. // If the error is a Win32 make it back to a Win32 error else send
  563. // the HR in the service specific exit code
  564. if ( FACILITY_WIN32 == HRESULT_FACILITY(hr) ){
  565. m_status.dwWin32ExitCode = HRESULT_CODE(hr) ;}else{
  566. m_status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
  567. m_status.dwServiceSpecificExitCode = hr ;}
  568. LogEvent( FSA_MESSAGE_SERVICE_INITIALIZATION_FAILED , WsbHrAsString(hr), NULL );
  569. );
  570. }
  571. WsbTrace (OLESTR("Fsa: Created=%ls , Initialized=%ls\n"),
  572. WsbBoolAsString(g_bFsaCreated), WsbBoolAsString(g_bFsaInitialized));
  573. // initialize Engine server
  574. if ((! g_pEngServer) && (hr == S_OK)) {
  575. try {
  576. //
  577. // Create and initialize the server.
  578. //
  579. WsbAffirmHr( CoCreateInstance( CLSID_HsmServer, 0, CLSCTX_SERVER, IID_IHsmServer, (void **)&g_pEngServer ) );
  580. g_bEngCreated = TRUE;
  581. CComPtr<IWsbServer> pWsbServer;
  582. WsbAffirmHr(g_pEngServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer));
  583. WsbAffirmHrOk(pWsbServer->SetTrace(g_pTrace));
  584. WsbAffirmHr(g_pEngServer->Init());
  585. g_bEngInitialized = TRUE;
  586. }WsbCatchAndDo(hr,
  587. // If the error is a Win32 make it back to a Win32 error else send
  588. // the HR in the service specific exit code
  589. if ( FACILITY_WIN32 == HRESULT_FACILITY(hr) ){
  590. m_status.dwWin32ExitCode = HRESULT_CODE(hr) ;}else{
  591. m_status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
  592. m_status.dwServiceSpecificExitCode = hr ;}
  593. LogEvent( HSM_MESSAGE_SERVICE_CREATE_FAILED, WsbHrAsString(hr), NULL );
  594. );
  595. }
  596. WsbTrace (OLESTR("Engine: Created=%ls , Initialized=%ls\n"),
  597. WsbBoolAsString(g_bEngCreated), WsbBoolAsString(g_bEngInitialized));
  598. if (hr == S_OK) {
  599. SetServiceStatus(SERVICE_RUNNING);
  600. LogEvent( HSM_MESSAGE_SERVICE_STARTED, NULL );
  601. MSG msg;
  602. while (GetMessage(&msg, 0, 0, 0)) {
  603. // If something has changed with the devices, then rescan. At somepoint we
  604. // may want to do a more limited scan (i.e. just update what changed), but this
  605. // should cover it for now.
  606. //
  607. // Since something has changed, we will also force a rewrite of the persistant data.
  608. if (WM_DEVICECHANGE == msg.message) {
  609. CComPtr<IWsbServer> pWsbServer;
  610. try {
  611. WsbAffirmHr(g_pFsaServer->ScanForResources());
  612. WsbAffirmHr(g_pFsaServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer));
  613. WsbAffirmHr(pWsbServer->SaveAll());
  614. }WsbCatchAndDo(hr,
  615. // If we had a problem then log a message and exit the service. We don't
  616. // want to leave the service running, since we might have invalid drive
  617. // mappings.
  618. LogEvent(FSA_MESSAGE_RESCANFAILED, WsbHrAsString(hr), NULL);
  619. PostMessage(NULL, WM_QUIT, 0, 0);
  620. );
  621. pWsbServer = 0;
  622. }
  623. DispatchMessage(&msg);
  624. }
  625. }
  626. LogEvent( HSM_MESSAGE_SERVICE_EXITING, NULL );
  627. // TEMPORARY - call a function so we can break before release.
  628. DebugRelease ();
  629. // prepare for releasing Eng server
  630. if ((g_pEngServer != 0) && g_bEngCreated && g_bEngInitialized) {
  631. // Save out server data
  632. HSM_SYSTEM_STATE SysState;
  633. SysState.State = HSM_STATE_SHUTDOWN;
  634. hr = g_pEngServer->ChangeSysState(&SysState);
  635. if (FAILED(hr)) {
  636. LogEvent( HSM_MESSAGE_SERVICE_FAILED_TO_SHUTDOWN, WsbHrAsString(hr), NULL );
  637. }
  638. }
  639. // Prepare for releasing Fsa server
  640. if ((g_pFsaServer != 0) && g_bFsaCreated && g_bFsaInitialized) {
  641. CComPtr<IWsbServer> pWsbServer;
  642. HSM_SYSTEM_STATE SysState;
  643. hr = g_pFsaServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer);
  644. if (hr == S_OK) {
  645. hr = pWsbServer->SaveAll();
  646. }
  647. if (FAILED(hr)) {
  648. LogEvent( FSA_MESSAGE_SERVICE_FAILED_TO_SAVE_DATABASE, WsbHrAsString(hr), NULL );
  649. }
  650. pWsbServer = 0;
  651. // Persist the databases and release everything
  652. SysState.State = HSM_STATE_SHUTDOWN;
  653. hr = g_pFsaServer->ChangeSysState(&SysState);
  654. if (FAILED(hr)) {
  655. LogEvent( FSA_MESSAGE_SERVICE_FAILED_TO_SHUTDOWN, WsbHrAsString(hr), NULL );
  656. }
  657. }
  658. // Release Eng server
  659. if (g_bEngCreated && (g_pEngServer != 0)) {
  660. // Free server inside a crit. section thus avoid conflicts with accessing clients
  661. EnterCriticalSection(&g_EngCriticalSection);
  662. g_bEngInitialized = FALSE;
  663. g_bEngCreated = FALSE;
  664. // Disconnect all remote clients
  665. (void)CoDisconnectObject(g_pEngServer, 0);
  666. // Forse object destroy, ignore reference count here
  667. IWsbServer *pWsbServer;
  668. hr = g_pEngServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer);
  669. if (hr == S_OK) {
  670. pWsbServer->Release();
  671. pWsbServer->DestroyObject();
  672. }
  673. g_pEngServer = 0;
  674. LeaveCriticalSection (&g_EngCriticalSection);
  675. }
  676. // Release Fsa server
  677. if (g_bFsaCreated && (g_pFsaServer != 0)) {
  678. // Free server inside a crit. section thus avoid conflicts with accessing clients
  679. EnterCriticalSection(&g_FsaCriticalSection);
  680. g_bFsaInitialized = FALSE;
  681. g_bFsaCreated = FALSE;
  682. // Disconnect all remote clients
  683. (void)CoDisconnectObject(g_pFsaServer, 0);
  684. // Forse object destroy, ignore reference count here
  685. IWsbServer *pWsbServer;
  686. hr = g_pFsaServer->QueryInterface(IID_IWsbServer, (void**) &pWsbServer);
  687. if (hr == S_OK) {
  688. pWsbServer->Release();
  689. pWsbServer->DestroyObject();
  690. }
  691. g_pFsaServer = 0;
  692. LeaveCriticalSection(&g_FsaCriticalSection);
  693. }
  694. _Module.RevokeClassObjects();
  695. WsbTraceOut(OLESTR("CServiceModule::Run"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  696. g_pTrace = 0;
  697. CoUninitialize();
  698. // Delete the server critical section
  699. DeleteCriticalSection(&g_EngCriticalSection);
  700. DeleteCriticalSection(&g_FsaCriticalSection);
  701. }WsbCatch(hr);
  702. }
  703. //
  704. // Tries to start the service as a console application
  705. // (not through SCM calls)
  706. //
  707. static void ConsoleApp()
  708. {
  709. HRESULT hr;
  710. ::SetConsoleCtrlHandler(ConsoleHandler, TRUE) ;
  711. // set Registry for process
  712. hr = CoInitialize (NULL);
  713. if (SUCCEEDED(hr)) {
  714. hr = _Module.UpdateRegistryFromResourceD(IDR_Serv2Proc, TRUE);
  715. CoUninitialize();
  716. _Module.Run();
  717. //
  718. // set Registry back for service
  719. hr = CoInitialize (NULL);
  720. if (SUCCEEDED(hr)) {
  721. hr = _Module.UpdateRegistryFromResourceD(IDR_Proc2Serv, TRUE);
  722. CoUninitialize();
  723. }
  724. }
  725. }
  726. //
  727. // Callback function for handling console events
  728. //
  729. BOOL WINAPI ConsoleHandler(DWORD dwCtrlType)
  730. {
  731. switch (dwCtrlType) {
  732. case CTRL_BREAK_EVENT:
  733. case CTRL_C_EVENT:
  734. case CTRL_CLOSE_EVENT:
  735. case CTRL_LOGOFF_EVENT:
  736. case CTRL_SHUTDOWN_EVENT:
  737. PostThreadMessage(_Module.dwThreadID, WM_QUIT, 0, 0);
  738. return TRUE;
  739. }
  740. return FALSE ;
  741. }
  742. /////////////////////////////////////////////////////////////////////////////
  743. //
  744. extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
  745. HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
  746. {
  747. _Module.Init(ObjectMap, hInstance);
  748. TCHAR szTokens[] = _T("-/");
  749. LPTSTR lpszToken = _tcstok(lpCmdLine, szTokens);
  750. while (lpszToken != NULL) {
  751. if (_tcsicmp(lpszToken, _T("UnregServer"))==0) {
  752. return _Module.UnregisterServer();
  753. }
  754. if (_tcsicmp(lpszToken, _T("RegServer"))==0) {
  755. return _Module.RegisterServer(FALSE);
  756. }
  757. #ifdef DBG
  758. if (_tcsicmp(lpszToken, _T("D"))==0) {
  759. _Module.m_bService = FALSE;
  760. }
  761. #endif
  762. lpszToken = _tcstok(NULL, szTokens);
  763. }
  764. //
  765. // Cheap hack to force the ESE.DLL to be loaded before any other threads are started
  766. //
  767. LoadLibrary( L"RsIdb.dll" );
  768. if (_Module.m_bService) {
  769. _Module.Start();
  770. } else {
  771. ConsoleApp ();
  772. }
  773. // When we get here, the service has been stopped
  774. return _Module.m_status.dwWin32ExitCode;
  775. }
  776. void DebugRelease ()
  777. {
  778. WsbTrace(OLESTR("DebugRelease in"));
  779. WsbTrace(OLESTR("DebugRelease out"));
  780. }