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.

764 lines
19 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. service.cpp
  5. Abstract:
  6. This file provides access to the service control
  7. manager for starting, stopping, adding, and removing
  8. services.
  9. Environment:
  10. WIN32 User Mode
  11. Author:
  12. Vlad Sadovsky (vlads) 17-Apr-1998
  13. --*/
  14. //
  15. // Precompiled header
  16. //
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. //
  20. // Include
  21. //
  22. #include "sti_ci.h"
  23. #include "device.h"
  24. #include <regstr.h>
  25. #include <sti.h>
  26. #include <stiregi.h>
  27. #include <stilib.h>
  28. #include <stidebug.h>
  29. #include <stiapi.h>
  30. #include <stisvc.h>
  31. #include <eventlog.h>
  32. //
  33. // Extern
  34. //
  35. extern HINSTANCE g_hDllInstance;
  36. //
  37. // Prototype
  38. //
  39. DWORD
  40. SetServiceSecurity(
  41. LPTSTR AccountName
  42. );
  43. DLLEXPORT
  44. VOID
  45. CALLBACK
  46. InstallWiaService(
  47. HWND hwnd,
  48. HINSTANCE hinst,
  49. LPTSTR lpszCmdLine,
  50. int nCmdShow
  51. );
  52. //
  53. // Function
  54. //
  55. DWORD
  56. WINAPI
  57. StiServiceInstall(
  58. BOOL UseLocalSystem,
  59. BOOL DemandStart,
  60. LPTSTR lpszUserName,
  61. LPTSTR lpszUserPassword
  62. )
  63. /*++
  64. Routine Description:
  65. Service installation function.
  66. Calls SCM to install STI service, which is running in user security context
  67. Arguments:
  68. Return Value:
  69. None.
  70. --*/
  71. {
  72. DWORD dwError = NOERROR;
  73. SC_HANDLE hSCM = NULL;
  74. SC_HANDLE hService = NULL;
  75. SERVICE_DESCRIPTION ServiceDescroption;
  76. TCHAR szServiceDesc[MAX_PATH];
  77. TCHAR szServiceName[MAX_PATH];
  78. __try {
  79. hSCM = ::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
  80. if (!hSCM) {
  81. dwError = GetLastError();
  82. __leave;
  83. }
  84. //
  85. // If service already exists change startup type, else CreateService.
  86. // NOTE: The service should already be installed - if it isn't, we're
  87. // patching it here because it MUST be installed in order to use WIA.
  88. //
  89. hService = OpenService(
  90. hSCM,
  91. STI_SERVICE_NAME,
  92. SERVICE_ALL_ACCESS
  93. );
  94. if (hService) {
  95. //
  96. // Change the service config parameters. Note: we're only changing StartType
  97. //
  98. if (!ChangeServiceConfig(hService, // handle to WIA service
  99. SERVICE_NO_CHANGE, // Don't change ServiceType
  100. DemandStart ? SERVICE_DEMAND_START : SERVICE_AUTO_START, // Change StartType
  101. SERVICE_NO_CHANGE, // Don't change ErrorControl
  102. NULL, // Don't change BinaryPathName
  103. NULL, // Don't change LoadOrderGroup
  104. NULL, // Don't change TagId
  105. NULL, // Don't change Dependencies
  106. NULL, // Don't change ServiceStartName
  107. NULL, // Don't change Password
  108. NULL)) { // Don't change DisplayName
  109. dwError = GetLastError();
  110. DebugTrace(TRACE_ERROR,(("StiServiceInstall: ChangeServiceConfig() failed. Err=0x%x.\r\n"), dwError));
  111. __leave;
  112. } // if (!ChangeServiceConfig(...))
  113. } else {
  114. //
  115. // If use local system - set security
  116. //
  117. if (!UseLocalSystem) {
  118. #ifdef LATER
  119. dwError = SetServiceSecurity( lpszUserName );
  120. if (dwError) {
  121. dwError = ERROR_SERVICE_LOGON_FAILED ;
  122. __leave;
  123. }
  124. #endif
  125. }
  126. //
  127. // Load service name.
  128. //
  129. if(0 == LoadString(g_hDllInstance, WiaServiceName, szServiceName, MAX_PATH)){
  130. dwError = GetLastError();
  131. __leave;
  132. } // if(0 != LoadString(g_hDllInstance, WiaServiceName, szServiceName, MAX_PATH))
  133. hService = CreateService(
  134. hSCM,
  135. STI_SERVICE_NAME,
  136. szServiceName,
  137. SERVICE_ALL_ACCESS,
  138. STI_SVC_SERVICE_TYPE,
  139. DemandStart ? SERVICE_DEMAND_START : SERVICE_AUTO_START,
  140. SERVICE_ERROR_NORMAL,
  141. STI_IMAGE_NAME_SVCHOST,
  142. NULL,
  143. NULL,
  144. STI_SVC_DEPENDENCIES, //STI_SERVICE_DEPENDENCY,
  145. UseLocalSystem ? NULL : lpszUserName,
  146. UseLocalSystem ? NULL : lpszUserPassword
  147. );
  148. if (!hService) {
  149. dwError = GetLastError();
  150. DebugTrace(TRACE_ERROR,(("StiServiceInstall: CreateService() failed. Err=0x%x.\r\n"), dwError));
  151. __leave;
  152. }
  153. //
  154. // Load service description.
  155. //
  156. if(0 != LoadString(g_hDllInstance, WiaServiceDescription, szServiceDesc, MAX_PATH)){
  157. //
  158. // Change service description.
  159. //
  160. ServiceDescroption.lpDescription = (LPTSTR)szServiceDesc;
  161. ChangeServiceConfig2(hService,
  162. SERVICE_CONFIG_DESCRIPTION,
  163. (LPVOID)&ServiceDescroption);
  164. } // if(0 != LoadString(g_hDllInstance, WiaServiceDescription, szServiceDesc, MAX_PATH))
  165. }
  166. //
  167. // Add registry settings for event logging
  168. //
  169. RegisterStiEventSources();
  170. //
  171. // Start service if AUTO_START.
  172. //
  173. if(FALSE == DemandStart){
  174. if(!StartService(hService,0,(LPCTSTR *)NULL)){
  175. dwError = GetLastError();
  176. } // if(!StartService(hService,0,(LPCTSTR *)NULL))
  177. } // if(FALSE == DemandStart)
  178. }
  179. __finally {
  180. //
  181. // Close service handle.
  182. //
  183. if (NULL != hService) {
  184. CloseServiceHandle(hService);
  185. } // if(NULL != hService)
  186. if(NULL != hSCM){
  187. CloseServiceHandle( hSCM );
  188. } // if(NULL != hSCM)
  189. }
  190. return dwError;
  191. } //StiServiceInstall
  192. DWORD
  193. WINAPI
  194. StiServiceRemove(
  195. VOID
  196. )
  197. /*++
  198. Routine Description:
  199. Service removal function. This function calls SCM to remove the STI service.
  200. Arguments:
  201. None.
  202. Return Value:
  203. Return code. Return zero for success
  204. --*/
  205. {
  206. DWORD dwError = NOERROR;
  207. SC_HANDLE hSCM = NULL;
  208. SC_HANDLE hService = NULL;
  209. SERVICE_STATUS ServiceStatus;
  210. UINT uiRetry = 10;
  211. HKEY hkRun;
  212. __try {
  213. hSCM = ::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
  214. if (!hSCM) {
  215. dwError = GetLastError();
  216. DebugTrace(TRACE_ERROR,(("StiServiceRemove: OpenSCManager() failed. Err=0x%x.\r\n"), dwError));
  217. __leave;
  218. }
  219. hService = OpenService(
  220. hSCM,
  221. STI_SERVICE_NAME,
  222. SERVICE_ALL_ACCESS
  223. );
  224. if (!hService) {
  225. dwError = GetLastError();
  226. DebugTrace(TRACE_ERROR,(("StiServiceRemove: OpenService() failed. Err=0x%x.\r\n"), dwError));
  227. __leave;
  228. }
  229. //
  230. // Stop service first
  231. //
  232. if (ControlService( hService, SERVICE_CONTROL_STOP, &ServiceStatus )) {
  233. //
  234. // Wait a little
  235. //
  236. Sleep( STI_STOP_FOR_REMOVE_TIMEOUT );
  237. ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  238. while( QueryServiceStatus( hService, &ServiceStatus ) &&
  239. (SERVICE_STOP_PENDING == ServiceStatus.dwCurrentState)) {
  240. Sleep( STI_STOP_FOR_REMOVE_TIMEOUT );
  241. if (!uiRetry--) {
  242. break;
  243. }
  244. }
  245. if (ServiceStatus.dwCurrentState != SERVICE_STOPPED) {
  246. dwError = GetLastError();
  247. DebugTrace(TRACE_ERROR,(("StiServiceRemove: Unable to stop service. Err=0x%x.\r\n"), dwError));
  248. if(ServiceStatus.dwCurrentState != ERROR_SERVICE_NOT_ACTIVE) {
  249. __leave;
  250. } // if(ServiceStatus.dwCurrentState != ERROR_SERVICE_NOT_ACTIVE)
  251. } // if (ServiceStatus.dwCurrentState != SERVICE_STOPPED)
  252. } else { // if (ControlService( hService, SERVICE_CONTROL_STOP, &ServiceStatus ))
  253. dwError = GetLastError();
  254. DebugTrace(TRACE_ERROR,(("StiServiceRemove: ControlService() failed. Err=0x%x.\r\n"), dwError));
  255. //
  256. // If service hasn't been started yet, just ignore.
  257. //
  258. if(ERROR_SERVICE_NOT_ACTIVE != dwError){
  259. __leave;
  260. }
  261. }
  262. if (!DeleteService( hService )) {
  263. dwError = GetLastError();
  264. DebugTrace(TRACE_ERROR,(("StiServiceRemove: DeleteService() failed. Err=0x%x.\r\n"), dwError));
  265. __leave;
  266. } else {
  267. dwError = NOERROR;
  268. }
  269. }
  270. __finally {
  271. if(NULL != hService){
  272. CloseServiceHandle( hService );
  273. }
  274. if(NULL != hSCM){
  275. CloseServiceHandle( hSCM );
  276. }
  277. } // __finally
  278. //
  279. // Leftovers from Win9x - remove STI monitor from Run section
  280. //
  281. if (RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUN, &hkRun) == NO_ERROR) {
  282. RegDeleteValue (hkRun, REGSTR_VAL_MONITOR);
  283. RegCloseKey(hkRun);
  284. }
  285. return dwError;
  286. } // StiServiceRemove
  287. BOOL
  288. SetServiceDependency(
  289. LPTSTR ServiceName,
  290. LPTSTR DependentServiceName
  291. )
  292. {
  293. BOOL rVal = FALSE;
  294. SC_HANDLE hSvcMgr = NULL;
  295. SC_HANDLE hService = NULL;
  296. hSvcMgr = OpenSCManager(
  297. NULL,
  298. NULL,
  299. SC_MANAGER_ALL_ACCESS
  300. );
  301. if (!hSvcMgr) {
  302. goto exit;
  303. }
  304. hService = OpenService(
  305. hSvcMgr,
  306. ServiceName,
  307. SERVICE_ALL_ACCESS
  308. );
  309. if (!hService) {
  310. goto exit;
  311. }
  312. if (!ChangeServiceConfig(
  313. hService, // handle to service
  314. SERVICE_NO_CHANGE, // type of service
  315. SERVICE_NO_CHANGE, // when to start service
  316. SERVICE_NO_CHANGE, // severity if service fails to start
  317. NULL, // pointer to service binary file name
  318. NULL, // pointer to load ordering group name
  319. NULL, // pointer to variable to get tag identifier
  320. DependentServiceName, // pointer to array of dependency names
  321. NULL, // pointer to account name of service
  322. NULL, // pointer to password for service account
  323. NULL // pointer to display name
  324. )) {
  325. goto exit;
  326. }
  327. rVal = TRUE;
  328. exit:
  329. if(NULL != hService){
  330. CloseServiceHandle( hService );
  331. }
  332. if(NULL != hSvcMgr){
  333. CloseServiceHandle( hSvcMgr );
  334. }
  335. return rVal;
  336. }
  337. BOOL
  338. SetServiceStart(
  339. LPTSTR ServiceName,
  340. DWORD StartType
  341. )
  342. {
  343. BOOL rVal = FALSE;
  344. SC_HANDLE hSvcMgr = NULL;
  345. SC_HANDLE hService = NULL;
  346. hSvcMgr = OpenSCManager(
  347. NULL,
  348. NULL,
  349. SC_MANAGER_ALL_ACCESS
  350. );
  351. if (!hSvcMgr) {
  352. goto exit;
  353. }
  354. hService = OpenService(
  355. hSvcMgr,
  356. ServiceName,
  357. SERVICE_ALL_ACCESS
  358. );
  359. if (!hService) {
  360. goto exit;
  361. }
  362. if (!ChangeServiceConfig(
  363. hService, // handle to service
  364. SERVICE_NO_CHANGE, // type of service
  365. StartType, // when to start service
  366. SERVICE_NO_CHANGE, // severity if service fails to start
  367. NULL, // pointer to service binary file name
  368. NULL, // pointer to load ordering group name
  369. NULL, // pointer to variable to get tag identifier
  370. NULL, // pointer to array of dependency names
  371. NULL, // pointer to account name of service
  372. NULL, // pointer to password for service account
  373. NULL // pointer to display name
  374. ))
  375. {
  376. goto exit;
  377. }
  378. rVal = TRUE;
  379. exit:
  380. if(NULL != hService){
  381. CloseServiceHandle( hService );
  382. }
  383. if(NULL != hSvcMgr){
  384. CloseServiceHandle( hSvcMgr );
  385. }
  386. return rVal;
  387. }
  388. BOOL
  389. StartWiaService(
  390. VOID
  391. )
  392. {
  393. BOOL rVal = FALSE;
  394. SC_HANDLE hSvcMgr = NULL;
  395. SC_HANDLE hService = NULL;
  396. SERVICE_STATUS ServiceStatus;
  397. UINT uiRetry = 40; // start time is much larger than stop time.
  398. // Setting 40 sec just to be safe.
  399. DebugTrace(TRACE_PROC_ENTER,(("StartWiaService: Enter... \r\n")));
  400. //
  401. // Open Service Control Manager.
  402. //
  403. hSvcMgr = OpenSCManager(
  404. NULL,
  405. NULL,
  406. SC_MANAGER_ALL_ACCESS
  407. );
  408. if (!hSvcMgr) {
  409. DebugTrace(TRACE_ERROR,(("StartWiaService: ERROR!! OpenSCManager failed. Err=0x%x\n"), GetLastError()));
  410. goto exit;
  411. }
  412. //
  413. // Open WIA service.
  414. //
  415. hService = OpenService(
  416. hSvcMgr,
  417. STI_SERVICE_NAME,
  418. SERVICE_ALL_ACCESS
  419. );
  420. if (!hService) {
  421. DebugTrace(TRACE_ERROR,(("StartWiaService: ERROR!! OpenService failed, re-creating Service Entry (Err=0x%x)\n"), GetLastError()));
  422. //
  423. // Attempt to re-install service
  424. //
  425. InstallWiaService(NULL,
  426. NULL,
  427. NULL,
  428. 0);
  429. Sleep(3000);
  430. //
  431. // Try to open it again
  432. //
  433. hService = OpenService(
  434. hSvcMgr,
  435. STI_SERVICE_NAME,
  436. SERVICE_ALL_ACCESS
  437. );
  438. if (!hService) {
  439. DebugTrace(TRACE_ERROR,(("StartWiaService: ERROR!! OpenService failed for the second time. Err=0x%x\n"), GetLastError()));
  440. goto exit;
  441. }
  442. }
  443. rVal = StartService(hService,
  444. 0,
  445. (LPCTSTR *)NULL);
  446. if(!rVal){
  447. DebugTrace(TRACE_STATUS,(("StartWiaService: ERROR!! StartService failed. Err=0x%x\n"), GetLastError()));
  448. goto exit;
  449. }
  450. //
  451. // Wait for WIA service to really start.
  452. //
  453. Sleep( STI_STOP_FOR_REMOVE_TIMEOUT );
  454. ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  455. while( QueryServiceStatus( hService, &ServiceStatus ) &&
  456. (SERVICE_START_PENDING == ServiceStatus.dwCurrentState)) {
  457. Sleep( STI_STOP_FOR_REMOVE_TIMEOUT );
  458. if (!uiRetry--) {
  459. break;
  460. }
  461. }
  462. if (ServiceStatus.dwCurrentState != SERVICE_RUNNING) {
  463. DebugTrace(TRACE_ERROR,(("StartWiaService: ERROR!! Hit timeout to start service. Err=0x%x\n"), GetLastError()));
  464. }
  465. exit:
  466. if(NULL != hService){
  467. CloseServiceHandle( hService );
  468. }
  469. if(NULL != hSvcMgr){
  470. CloseServiceHandle( hSvcMgr );
  471. }
  472. DebugTrace(TRACE_PROC_LEAVE,(("StartWiaService: Leaving... Ret=0x%x\n"), rVal));
  473. return rVal;
  474. }
  475. BOOL
  476. StopWiaService(
  477. VOID
  478. )
  479. {
  480. BOOL rVal = FALSE;
  481. SC_HANDLE hSvcMgr = NULL;
  482. SC_HANDLE hService = NULL;
  483. SERVICE_STATUS ServiceStatus;
  484. UINT uiRetry = 10;
  485. DebugTrace(TRACE_PROC_ENTER,(("StopWiaService: Enter... \r\n")));
  486. //
  487. // Open Service Control Manager.
  488. //
  489. hSvcMgr = OpenSCManager(
  490. NULL,
  491. NULL,
  492. SC_MANAGER_ALL_ACCESS
  493. );
  494. if (!hSvcMgr) {
  495. DebugTrace(TRACE_ERROR,(("StopWiaService: ERROR!! OpenSCManager failed. Err=0x%x\n"), GetLastError()));
  496. goto exit;
  497. }
  498. //
  499. // Open WIA service.
  500. //
  501. hService = OpenService(
  502. hSvcMgr,
  503. STI_SERVICE_NAME,
  504. SERVICE_ALL_ACCESS
  505. );
  506. if (!hService) {
  507. DebugTrace(TRACE_ERROR,(("StopWiaService: ERROR!! OpenService failed. Err=0x%x\n"), GetLastError()));
  508. goto exit;
  509. }
  510. //
  511. // Stop WIA service.
  512. //
  513. rVal = ControlService(hService,
  514. SERVICE_CONTROL_STOP,
  515. &ServiceStatus);
  516. if(!rVal){
  517. DebugTrace(TRACE_ERROR,(("StopWiaService: ERROR!! ControlService failed. Err=0x%x\n"), GetLastError()));
  518. } else {
  519. //
  520. // Wait for WIA service really stops.
  521. //
  522. Sleep( STI_STOP_FOR_REMOVE_TIMEOUT );
  523. ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  524. while( QueryServiceStatus( hService, &ServiceStatus ) &&
  525. (SERVICE_STOP_PENDING == ServiceStatus.dwCurrentState)) {
  526. Sleep( STI_STOP_FOR_REMOVE_TIMEOUT );
  527. if (!uiRetry--) {
  528. break;
  529. }
  530. }
  531. if (ServiceStatus.dwCurrentState != SERVICE_STOPPED) {
  532. DebugTrace(TRACE_ERROR,(("StopWiaService: ERROR!! Hit timeout to stop service. Err=0x%x\n"), GetLastError()));
  533. }
  534. }
  535. exit:
  536. if(NULL != hService){
  537. CloseServiceHandle( hService );
  538. }
  539. if(NULL != hSvcMgr){
  540. CloseServiceHandle( hSvcMgr );
  541. }
  542. DebugTrace(TRACE_PROC_LEAVE,(("StopWiaService: Leaving... Ret=0x%x\n"), rVal));
  543. return rVal;
  544. }
  545. /*
  546. BOOL
  547. SetServiceAccount(
  548. LPTSTR ServiceName,
  549. PSECURITY_INFO SecurityInfo
  550. )
  551. {
  552. BOOL rVal = FALSE;
  553. SC_HANDLE hSvcMgr;
  554. SC_HANDLE hService;
  555. hSvcMgr = OpenSCManager(
  556. NULL,
  557. NULL,
  558. SC_MANAGER_ALL_ACCESS
  559. );
  560. if (!hSvcMgr) {
  561. goto exit;
  562. }
  563. hService = OpenService(
  564. hSvcMgr,
  565. ServiceName,
  566. SERVICE_ALL_ACCESS
  567. );
  568. if (!hService) {
  569. goto exit;
  570. }
  571. if (!ChangeServiceConfig(
  572. hService, // handle to service
  573. SERVICE_NO_CHANGE, // type of service
  574. SERVICE_NO_CHANGE, // when to start service
  575. SERVICE_NO_CHANGE, // severity if service fails to start
  576. NULL, // pointer to service binary file name
  577. NULL, // pointer to load ordering group name
  578. NULL, // pointer to variable to get tag identifier
  579. NULL, // pointer to array of dependency names
  580. SecurityInfo->AccountName, // pointer to account name of service
  581. SecurityInfo->Password, // pointer to password for service account
  582. NULL // pointer to display name
  583. )) {
  584. goto exit;
  585. }
  586. rVal = TRUE;
  587. exit:
  588. CloseServiceHandle( hService );
  589. CloseServiceHandle( hSvcMgr );
  590. return rVal;
  591. }
  592. */