SrvManager.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. #include "stdafx2.h"
  2. #include "SrvManager.h"
  3. CRITICAL_SECTION s_cs;
  4. CSvcManager* CSvcManager::m_pInstance = new CSvcManager();
  5. CSvcManager::CSvcManager(void)
  6. :m_schSCManager(NULL),
  7. m_bInit(FALSE)
  8. {
  9. memset(m_LastErrInfo.szErrMsg, '\0', sizeof(CHAR)*MAX_ERR_MSG_SIZE);
  10. m_LastErrInfo.dwErrMsgLen = 0;
  11. m_LastErrInfo.dwLastErrCode = 0;
  12. Init();
  13. }
  14. CSvcManager::~CSvcManager(void)
  15. {
  16. Release();
  17. }
  18. BOOLEAN CSvcManager::Init()
  19. {
  20. if(m_bInit == TRUE)
  21. return TRUE;
  22. BOOLEAN bCode = TRUE;
  23. m_schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  24. if (!m_schSCManager)
  25. {
  26. DWORD dwErrCode = GetLastError();
  27. m_LastErrInfo.dwLastErrCode = dwErrCode;
  28. SaveLastErrMsg("Open SC Manager failed with status %d ", dwErrCode);
  29. return m_bInit = FALSE;
  30. }
  31. CoverLastErrMsg();
  32. return m_bInit = TRUE;
  33. }
  34. BOOLEAN CSvcManager::InstallService(LPCTSTR szSrvName, LPCTSTR szServiceExe)
  35. {
  36. SC_HANDLE schService;
  37. DWORD err;
  38. //Create a new service object.
  39. schService = CreateServiceA(m_schSCManager, // handle of service control manager database
  40. szSrvName, // address of name of service to start
  41. szSrvName, // address of display name
  42. SERVICE_ALL_ACCESS, // type of access to service
  43. SERVICE_KERNEL_DRIVER, // type of service
  44. SERVICE_DEMAND_START, // when to start service
  45. SERVICE_ERROR_NORMAL, // severity if service fails to start
  46. szServiceExe, // address of name of binary file
  47. NULL, // service does not belong to a group
  48. NULL, // no tag requested
  49. NULL, // no dependency names
  50. NULL, // use LocalSystem account
  51. NULL // no password for service account
  52. );
  53. if (schService == NULL)
  54. {
  55. err = GetLastError();
  56. if (err == ERROR_SERVICE_EXISTS)
  57. {
  58. m_LastErrInfo.dwLastErrCode = err;
  59. SaveLastErrMsg("Warning: Previous instance of the service is existed");
  60. return TRUE;
  61. }
  62. else if (err == ERROR_SERVICE_MARKED_FOR_DELETE)
  63. {
  64. SaveLastErrMsg("Previous instance of the service is not fully deleted. Try again...");
  65. return FALSE;
  66. }
  67. else
  68. {
  69. m_LastErrInfo.dwLastErrCode = err;
  70. SaveLastErrMsg("Create Service failed with status ", err);
  71. return FALSE;
  72. }
  73. }
  74. if (schService)
  75. {
  76. CloseServiceHandle(schService);
  77. }
  78. CoverLastErrMsg();
  79. return TRUE;
  80. }
  81. BOOLEAN CSvcManager::StartServiceWith(LPCTSTR szSrvName)
  82. {
  83. SC_HANDLE schService;
  84. DWORD errCode;
  85. schService = OpenServiceA(m_schSCManager, szSrvName, SERVICE_ALL_ACCESS);
  86. if (schService == NULL)
  87. {
  88. errCode = GetLastError();
  89. m_LastErrInfo.dwLastErrCode = errCode;
  90. SaveLastErrMsg("Open Service failed with status %d", errCode);
  91. return FALSE;
  92. }
  93. if (!StartServiceA(schService, 0, NULL))
  94. {
  95. errCode = GetLastError();
  96. if (errCode == ERROR_SERVICE_ALREADY_RUNNING)
  97. {
  98. SaveLastErrMsg("Service is already running.");
  99. return TRUE;
  100. }
  101. else
  102. {
  103. SaveLastErrMsg("Start Service failed with status %d", errCode);
  104. m_LastErrInfo.dwLastErrCode = errCode;
  105. return FALSE;
  106. }
  107. }
  108. if (schService)
  109. {
  110. CloseServiceHandle(schService);
  111. }
  112. CoverLastErrMsg();
  113. return TRUE;
  114. }
  115. BOOLEAN CSvcManager::QueryServiceStatus(LPCTSTR szSrvName, ServiceStatus& status)
  116. {
  117. BOOLEAN bCode = TRUE;
  118. SC_HANDLE schService;
  119. SERVICE_STATUS_PROCESS ssp;
  120. DWORD dwStartTime = GetTickCount();
  121. DWORD dwBytesNeeded;
  122. DWORD dwTimeout = 30000; // 30-second time-out
  123. DWORD dwWaitTime;
  124. status = SERVICE_STATUS_UNKNOWN;
  125. schService = OpenServiceA(m_schSCManager, szSrvName, SERVICE_QUERY_STATUS);
  126. if (schService == NULL)
  127. {
  128. DWORD dwErrCode = GetLastError();
  129. m_LastErrInfo.dwLastErrCode = dwErrCode;
  130. SaveLastErrMsg("Open Service failed with status %d", dwErrCode);
  131. return FALSE;
  132. }
  133. if(!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO,
  134. (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
  135. {
  136. DWORD dwErrCode = GetLastError();
  137. m_LastErrInfo.dwLastErrCode = dwErrCode;
  138. SaveLastErrMsg("QueryServiceStatusEx failed (%d)", dwErrCode);
  139. CloseServiceHandle(schService);
  140. return FALSE;
  141. }
  142. while(ssp.dwCurrentState == SERVICE_STOP_PENDING
  143. || ssp.dwCurrentState == SERVICE_CONTINUE_PENDING
  144. || ssp.dwCurrentState == SERVICE_START_PENDING
  145. || ssp.dwCurrentState == SERVICE_PAUSE_PENDING)
  146. {
  147. SaveLastErrMsg("Service current status is pending...");
  148. //dwWaitTime = ssp.dwWaitHint / 10;
  149. //if(dwWaitTime < 1000)
  150. // dwWaitTime = 1000;
  151. //else if(dwWaitTime > 10000)
  152. // dwWaitTime = 10000;
  153. dwWaitTime = 1500;
  154. Sleep(dwWaitTime);
  155. if(!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO,
  156. (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
  157. {
  158. DWORD dwErrCode = GetLastError();
  159. m_LastErrInfo.dwLastErrCode = dwErrCode;
  160. SaveLastErrMsg("QueryServiceStatusEx failed (%d)", dwErrCode);
  161. CloseServiceHandle(schService);
  162. return FALSE;
  163. }
  164. if(GetTickCount() - dwStartTime > dwTimeout)
  165. {
  166. SaveLastErrMsg("Query Service timed out.");
  167. CloseServiceHandle(schService);
  168. return FALSE;
  169. }
  170. }
  171. if(ssp.dwCurrentState == SERVICE_STOPPED)
  172. {
  173. status = SERVICE_STATUS_STOPPED;
  174. }
  175. else if(ssp.dwCurrentState == SERVICE_RUNNING)
  176. {
  177. status = SERVICE_STATUS_RUNNING;
  178. }
  179. else if(ssp.dwCurrentState == SERVICE_PAUSED)
  180. {
  181. status = SERVICE_STATUS_PASUSED;
  182. }
  183. CloseServiceHandle(schService);
  184. return TRUE;
  185. }
  186. BOOLEAN CSvcManager::RemoveService(LPCTSTR szSrvName)
  187. {
  188. SC_HANDLE schService;
  189. BOOLEAN bCode = TRUE;
  190. StopService(szSrvName);
  191. schService = OpenServiceA(m_schSCManager, szSrvName, SERVICE_ALL_ACCESS);
  192. if (schService == NULL)
  193. {
  194. DWORD dwErrCode = GetLastError();
  195. m_LastErrInfo.dwLastErrCode = dwErrCode;
  196. SaveLastErrMsg("Open Service failed with status %d", dwErrCode);
  197. return FALSE;
  198. }
  199. if (DeleteService(schService))
  200. {
  201. CoverLastErrMsg();
  202. bCode = TRUE;
  203. }
  204. else
  205. {
  206. DWORD dwErrCode = GetLastError();
  207. m_LastErrInfo.dwLastErrCode = dwErrCode;
  208. SaveLastErrMsg("Delete Service failed with status %d.", dwErrCode);
  209. bCode = FALSE;
  210. }
  211. if (schService)
  212. {
  213. CloseServiceHandle(schService);
  214. }
  215. return bCode;
  216. }
  217. BOOLEAN CSvcManager::Release()
  218. {
  219. if(m_bInit)
  220. {
  221. CloseServiceHandle(m_schSCManager);
  222. m_bInit = FALSE;
  223. m_schSCManager = NULL;
  224. }
  225. return m_bInit;
  226. }
  227. void CSvcManager::GetLastErrMsg(LastErrorInfo& lastInfo)
  228. {
  229. lastInfo.dwLastErrCode = m_LastErrInfo.dwLastErrCode;
  230. lastInfo.dwErrMsgLen = m_LastErrInfo.dwErrMsgLen;
  231. memcpy_s(lastInfo.szErrMsg, MAX_ERR_MSG_SIZE,
  232. m_LastErrInfo.szErrMsg, m_LastErrInfo.dwErrMsgLen+1);
  233. }
  234. void CSvcManager::SaveLastErrMsg(LPCTSTR fmt, ...)
  235. {
  236. va_list arg;
  237. va_start(arg, fmt);
  238. int n = _vscprintf(fmt, arg);
  239. if(n > 0)
  240. {
  241. memset(m_LastErrInfo.szErrMsg, 0, sizeof(CHAR)*MAX_ERR_MSG_SIZE);
  242. vsprintf_s(m_LastErrInfo.szErrMsg, MAX_ERR_MSG_SIZE, fmt, arg);
  243. m_LastErrInfo.dwErrMsgLen = n;
  244. }
  245. va_end(arg);
  246. }
  247. CSvcManager* CSvcManager::GetInstance()
  248. {
  249. return m_pInstance;
  250. }
  251. BOOLEAN CSvcManager::StopService(LPCTSTR szSrvName)
  252. {
  253. SC_HANDLE schService;
  254. BOOLEAN bCode = TRUE;
  255. SERVICE_STATUS_PROCESS ssp;
  256. DWORD dwStartTime = GetTickCount();
  257. DWORD dwBytesNeeded;
  258. DWORD dwTimeout = 30000; // 30-second time-out
  259. DWORD dwWaitTime;
  260. schService = OpenServiceA(m_schSCManager, szSrvName,
  261. SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS);
  262. if (schService == NULL)
  263. {
  264. DWORD dwErrCode = GetLastError();
  265. m_LastErrInfo.dwLastErrCode = dwErrCode;
  266. SaveLastErrMsg("Open Service failed with status %d", dwErrCode);
  267. return FALSE;
  268. }
  269. if(!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO,
  270. (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
  271. {
  272. DWORD dwErrCode = GetLastError();
  273. m_LastErrInfo.dwLastErrCode = dwErrCode;
  274. SaveLastErrMsg("QueryServiceStatusEx failed (%d)", dwErrCode);
  275. bCode = FALSE;
  276. }
  277. else
  278. {
  279. if(ssp.dwCurrentState == SERVICE_STOPPED)
  280. {
  281. m_LastErrInfo.dwLastErrCode = SERVICE_STOPPED;
  282. SaveLastErrMsg("Service is already stopped.");
  283. }
  284. else
  285. {
  286. while (ssp.dwCurrentState == SERVICE_STOP_PENDING)
  287. {
  288. SaveLastErrMsg("Service stop pending...");
  289. // Do not wait longer than the wait hint. A good interval is
  290. // one-tenth of the wait hint but not less than 1 second
  291. // and not more than 10 seconds.
  292. //dwWaitTime = ssp.dwWaitHint / 10;
  293. //if(dwWaitTime < 1000)
  294. // dwWaitTime = 1000;
  295. //else if(dwWaitTime > 10000)
  296. // dwWaitTime = 10000;
  297. dwWaitTime = 1500;
  298. Sleep(dwWaitTime);
  299. if(!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO,
  300. (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
  301. {
  302. DWORD dwErrCode = GetLastError();
  303. m_LastErrInfo.dwLastErrCode = dwErrCode;
  304. SaveLastErrMsg("QueryServiceStatusEx failed (%d)", dwErrCode);
  305. CloseServiceHandle(schService);
  306. return FALSE;
  307. }
  308. else
  309. {
  310. if(ssp.dwCurrentState == SERVICE_STOPPED)
  311. {
  312. m_LastErrInfo.dwLastErrCode = SERVICE_STOPPED;
  313. SaveLastErrMsg("Service stopped successfully.");
  314. CloseServiceHandle(schService);
  315. return TRUE;
  316. }
  317. else
  318. {
  319. if(GetTickCount() - dwStartTime > dwTimeout)
  320. {
  321. SaveLastErrMsg("Service stop timed out.");
  322. bCode = FALSE;
  323. break;
  324. }
  325. }
  326. }
  327. }
  328. StopDependentServices(szSrvName);
  329. if(!ControlService(schService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp))
  330. {
  331. DWORD dwErrCode = GetLastError();
  332. m_LastErrInfo.dwLastErrCode = dwErrCode;
  333. SaveLastErrMsg("ControlService failed (%d).", dwErrCode);
  334. CloseServiceHandle(schService);
  335. return FALSE;
  336. }
  337. else
  338. {
  339. while (ssp.dwCurrentState != SERVICE_STOPPED)
  340. {
  341. //dwWaitTime = ssp.dwWaitHint / 10;
  342. //if(dwWaitTime < 1000)
  343. // dwWaitTime = 1000;
  344. //else if(dwWaitTime > 10000)
  345. // dwWaitTime = 10000;
  346. dwWaitTime = 1500;
  347. Sleep(dwWaitTime);
  348. if(!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO,
  349. (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
  350. {
  351. DWORD dwErrCode = GetLastError();
  352. m_LastErrInfo.dwLastErrCode = dwErrCode;
  353. SaveLastErrMsg("QueryServiceStatusEx failed (%d)", dwErrCode);
  354. CloseServiceHandle(schService);
  355. return FALSE;
  356. }
  357. if(ssp.dwCurrentState == SERVICE_STOPPED)
  358. {
  359. break;
  360. }
  361. if(GetTickCount() - dwStartTime > dwTimeout)
  362. {
  363. SaveLastErrMsg("Wait timed out.");
  364. bCode = FALSE;
  365. break;
  366. }
  367. }
  368. if(ssp.dwCurrentState == SERVICE_STOPPED)
  369. {
  370. m_LastErrInfo.dwLastErrCode = 0;
  371. SaveLastErrMsg("Service stopped successfully.");
  372. bCode = TRUE;
  373. }
  374. }
  375. }
  376. }
  377. if (schService)
  378. {
  379. CloseServiceHandle(schService);
  380. }
  381. return bCode;
  382. }
  383. BOOLEAN CSvcManager::StopDependentServices(LPCTSTR szSrvName)
  384. {
  385. SC_HANDLE schService;
  386. DWORD dwBytesNeeded;
  387. DWORD dwCount;
  388. DWORD dwWaitTime;
  389. LPENUM_SERVICE_STATUS lpDependencies = NULL;
  390. ENUM_SERVICE_STATUS ess;
  391. SC_HANDLE hDepService;
  392. SERVICE_STATUS_PROCESS ssp;
  393. DWORD dwStartTime = GetTickCount();
  394. DWORD dwTimeout = 30000; // 30-second time-out
  395. BOOLEAN bCode = TRUE;
  396. schService = OpenServiceA(m_schSCManager, szSrvName,
  397. SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS);
  398. if (schService == NULL)
  399. {
  400. DWORD dwErrCode = GetLastError();
  401. m_LastErrInfo.dwLastErrCode = dwErrCode;
  402. SaveLastErrMsg("Open Service failed with status %d", dwErrCode);
  403. return FALSE;
  404. }
  405. if(EnumDependentServicesA(schService, SERVICE_ACTIVE, lpDependencies, 0, &dwBytesNeeded, &dwCount))
  406. {
  407. SaveLastErrMsg("No dependent services.");
  408. CloseServiceHandle(schService);
  409. return TRUE;
  410. }
  411. DWORD dwErrCode = GetLastError();
  412. if(dwErrCode != ERROR_MORE_DATA)
  413. {
  414. m_LastErrInfo.dwLastErrCode = dwErrCode;
  415. SaveLastErrMsg("Unexpected error.");
  416. CloseServiceHandle(schService);
  417. return FALSE;
  418. }
  419. lpDependencies = (LPENUM_SERVICE_STATUS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded);
  420. if(!lpDependencies)
  421. {
  422. m_LastErrInfo.dwLastErrCode = GetLastError();
  423. SaveLastErrMsg("HeapAlloc failed.");
  424. CloseServiceHandle(schService);
  425. return FALSE;
  426. }
  427. __try {
  428. if(!EnumDependentServicesA(schService, SERVICE_ACTIVE,
  429. lpDependencies, dwBytesNeeded, &dwBytesNeeded, &dwCount))
  430. {
  431. m_LastErrInfo.dwLastErrCode = GetLastError();
  432. SaveLastErrMsg("EnumDependentServicesA failed.");
  433. return FALSE;
  434. }
  435. for(int idx=0; idx<dwCount; idx++)
  436. {
  437. ess = *(lpDependencies + idx);
  438. hDepService = OpenServiceA(m_schSCManager, ess.lpServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS);
  439. if(!hDepService)
  440. {
  441. m_LastErrInfo.dwLastErrCode = GetLastError();
  442. SaveLastErrMsg("OpenServiceA about %s failed.", ess.lpDisplayName);
  443. return FALSE;
  444. }
  445. __try {
  446. if(!ControlService(hDepService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp))
  447. {
  448. m_LastErrInfo.dwLastErrCode = GetLastError();
  449. SaveLastErrMsg("Stop Service %s failed.", ess.lpDisplayName);
  450. CloseServiceHandle(hDepService);
  451. CloseServiceHandle(schService);
  452. return FALSE;
  453. }
  454. while(ssp.dwCurrentState != SERVICE_STOPPED)
  455. {
  456. //dwWaitTime = ssp.dwWaitHint / 10;
  457. //if(dwWaitTime < 1000)
  458. // dwWaitTime = 1000;
  459. //else if(dwWaitTime > 10000)
  460. // dwWaitTime = 10000;
  461. dwWaitTime = 1500;
  462. Sleep(dwWaitTime);
  463. if(!QueryServiceStatusEx(hDepService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp,
  464. sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
  465. {
  466. m_LastErrInfo.dwLastErrCode = GetLastError();
  467. SaveLastErrMsg("Query status of Service %s failed.", ess.lpDisplayName);
  468. return FALSE;
  469. }
  470. if(ssp.dwCurrentState == SERVICE_STOPPED)
  471. {
  472. SaveLastErrMsg("Service %s is stopped.", ess.lpDisplayName);
  473. break;
  474. }
  475. if(GetTickCount() - dwStartTime > dwTimeout)
  476. {
  477. SaveLastErrMsg("Stop Service %s time out.", ess.lpDisplayName);
  478. return FALSE;
  479. }
  480. }
  481. }
  482. __finally
  483. {
  484. CloseServiceHandle(hDepService);
  485. }
  486. }
  487. }
  488. __finally
  489. {
  490. HeapFree(GetProcessHeap(), 0, lpDependencies);
  491. CloseServiceHandle(schService);
  492. }
  493. return TRUE;
  494. }
  495. BOOLEAN CSvcManager::RaiseUpPrivileges()
  496. {
  497. SaveLastErrMsg("RaiseUpPrivileges function is unImplemented.");
  498. return FALSE;
  499. }
  500. BOOLEAN CSvcManager::SetPrivilege(HANDLE hToken, // access token handle
  501. LPCTSTR lpszPrivilege, // name of privilege to enable/disable
  502. BOOL bEnablePrivilege // to enable or disable privilege
  503. )
  504. {
  505. TOKEN_PRIVILEGES tp;
  506. LUID luid;
  507. if ( !LookupPrivilegeValue(
  508. NULL, // lookup privilege on local system
  509. lpszPrivilege, // privilege to lookup
  510. &luid ) ) // receives LUID of privilege
  511. {
  512. SaveLastErrMsg("LookupPrivilegeValue error: %u", GetLastError() );
  513. return FALSE;
  514. }
  515. tp.PrivilegeCount = 1;
  516. tp.Privileges[0].Luid = luid;
  517. if (bEnablePrivilege)
  518. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  519. else
  520. tp.Privileges[0].Attributes = 0;
  521. // Enable the privilege or disable all privileges.
  522. if ( !AdjustTokenPrivileges(
  523. hToken,
  524. FALSE,
  525. &tp,
  526. sizeof(TOKEN_PRIVILEGES),
  527. (PTOKEN_PRIVILEGES) NULL,
  528. (PDWORD) NULL) )
  529. {
  530. SaveLastErrMsg("AdjustTokenPrivileges error: %u.", GetLastError() );
  531. return FALSE;
  532. }
  533. if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
  534. {
  535. SaveLastErrMsg("The token does not have the specified privilege.");
  536. return FALSE;
  537. }
  538. return TRUE;
  539. }