WindowService.cpp 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718
  1. #include "stdafx.h"
  2. #include "WindowService.h"
  3. #include <psapi.h>
  4. #include <tlhelp32.h>
  5. #pragma comment ( lib, "psapi.lib" )
  6. #include <Aclapi.h>
  7. #include <strsafe.h>
  8. #include <shlwapi.h>
  9. namespace WindowsService
  10. {
  11. //////////////////////////////////////////////////////////////////////////
  12. // 全局变量;
  13. //////////////////////////////////////////////////////////////////////////
  14. SERVICE_STATUS_HANDLE g_SvcStatusHandle; // 服务句柄;
  15. SERVICE_STATUS g_SvcStatus; // 服务状态;
  16. HANDLE g_hCtrlSvc = NULL; // 服务控制事件;
  17. TCHAR g_szlpSvrDescription[MAX_PATH] = _T(""); // 服务描述 ;
  18. TCHAR g_szSvcName[MAX_PATH] = _T(""); // 服务名称;
  19. WorkStartCallback g_lpStartWorkCallBack = NULL; // 开启工作者;
  20. WorkEndofCallback g_lpEndofWorkCallBack = NULL; // 结束工作者;
  21. //////////////////////////////////////////////////////////////////////////
  22. // 全局函数;
  23. int InitWinSock()
  24. {
  25. WORD wVersionRequested;
  26. WSADATA wsaData;
  27. int nErrCode;
  28. wVersionRequested = MAKEWORD(2, 2);
  29. nErrCode = WSAStartup( wVersionRequested, &wsaData );
  30. if ( 0 != nErrCode )
  31. return -1;
  32. return 0;
  33. }
  34. /************************************************************************/
  35. /* 函数:InitSvcVar;
  36. /* 描述:初始化服务变量;
  37. /* 参数:;
  38. /* 返回:void;
  39. /* 注意:;
  40. /* 示例:;
  41. /*
  42. /* 修改:;
  43. /* 日期:;
  44. /* 内容:;
  45. /************************************************************************/
  46. void InitSvcVar()
  47. {
  48. g_SvcStatusHandle = NULL;
  49. g_SvcStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS | SERVICE_INTERACTIVE_PROCESS; // | SERVICE_INTERACTIVE_PROCESS与桌面交互;
  50. g_SvcStatus.dwCurrentState = SERVICE_STOPPED;
  51. g_SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  52. g_SvcStatus.dwWin32ExitCode = 0;
  53. g_SvcStatus.dwServiceSpecificExitCode = 0;
  54. g_SvcStatus.dwCheckPoint = 0;
  55. g_SvcStatus.dwWaitHint = 0;
  56. }
  57. /************************************************************************/
  58. /* 函数:IsSvcInstalled;
  59. /* 描述:判断服务是否安装;
  60. /* 参数:;
  61. /* 返回:若服务已安装返回TRUE,否则返回FALSE;
  62. /* 注意:;
  63. /* 示例:;
  64. /*
  65. /* 修改:;
  66. /* 日期:;
  67. /* 内容:;
  68. /************************************************************************/
  69. BOOL IsSvcInstalled()
  70. {
  71. BOOL bResult = FALSE;
  72. // 打开服务控制管理器;
  73. SC_HANDLE schSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  74. if (schSCM != NULL)
  75. {// 打开服务;
  76. SC_HANDLE schSvc = ::OpenService(schSCM, g_szSvcName, SERVICE_QUERY_CONFIG);
  77. if (schSvc != NULL)
  78. {
  79. bResult = TRUE;
  80. ::CloseServiceHandle(schSvc);
  81. }
  82. ::CloseServiceHandle(schSCM);
  83. }
  84. return bResult;
  85. }
  86. /************************************************************************/
  87. /* 函数:SvcInstall;
  88. /* 描述:安装服务;
  89. /* 参数:;
  90. /* 返回:安装成功返回TRUE,否则返回FALSE;
  91. /* 注意:;
  92. /* 示例:;
  93. /*
  94. /* 修改:;
  95. /* 日期:;
  96. /* 内容:;
  97. /************************************************************************/
  98. BOOL SvcInstall()
  99. {
  100. // 获取服务程序的绝对路径;
  101. TCHAR szFilePath[MAX_PATH];
  102. if ( 0 == ::GetModuleFileName(NULL, szFilePath, MAX_PATH) )
  103. {
  104. _tprintf_s(_T("Cannot Install Service (%d)\n"), GetLastError());
  105. return FALSE;
  106. }
  107. // 打开服务控制管理器,获取SCM数据库句柄;
  108. SC_HANDLE schSCM = ::OpenSCManager(
  109. NULL, // 本地计算机;
  110. NULL, // ServicesActive database;
  111. SC_MANAGER_ALL_ACCESS // 所有权限;
  112. );
  113. if (schSCM == NULL)
  114. {
  115. _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
  116. return FALSE;
  117. }
  118. // 创建服务;
  119. SC_HANDLE schSvc = ::CreateService(
  120. schSCM, // SCM数据库;
  121. g_szSvcName, // 服务名称;
  122. g_szSvcName, // 服务描述;
  123. SERVICE_ALL_ACCESS, // 需要的访问权限;
  124. SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, // 服务类型;
  125. SERVICE_AUTO_START, //SERVICE_DEMAND_START, // 启动类型;
  126. SERVICE_ERROR_NORMAL, // 错误控制类型;
  127. szFilePath, // 服务程序路径;
  128. NULL, // 无加载顺序组;
  129. NULL, // 无标签标识;
  130. _T(""), // 无依赖;
  131. NULL, // 本地系统账号;
  132. NULL // 无密码(no password);
  133. );
  134. if ( schSvc == NULL )
  135. {
  136. _tprintf_s(_T("CreateService failed (%d)\n"), GetLastError());
  137. CloseServiceHandle(schSvc);
  138. return FALSE;
  139. }
  140. // 设置服务的描述;
  141. SERVICE_DESCRIPTION ServiceDesc;
  142. ServiceDesc.lpDescription = g_szlpSvrDescription;
  143. ::ChangeServiceConfig2(schSvc, SERVICE_CONFIG_DESCRIPTION, &ServiceDesc);
  144. // 释放资源;
  145. ::CloseServiceHandle(schSvc);
  146. ::CloseServiceHandle(schSCM);
  147. return TRUE;
  148. }
  149. /************************************************************************/
  150. /* 函数:ServiceMain;
  151. /* 描述:服务入口函数;
  152. /* 参数:;
  153. /* 返回:void;
  154. /* 注意:;
  155. /* 示例:;
  156. /*
  157. /* 修改:;
  158. /* 日期:;
  159. /* 内容:;
  160. /************************************************************************/
  161. void WINAPI ServiceMain()
  162. {
  163. // 注册服务的控制函数;
  164. g_SvcStatusHandle = RegisterServiceCtrlHandler(g_szSvcName, SvcCtrlHandler);
  165. if (g_SvcStatusHandle == NULL)
  166. {
  167. SvcReportEvent(_T("Handler not installed"));
  168. return;
  169. }
  170. // 在这里设置服务状态;
  171. g_SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  172. g_SvcStatus.dwServiceSpecificExitCode = 0;
  173. // 注册成功后向SCM报告服务状态信息,因为服务还没初始化完成;
  174. // 所以当前服务状态为SERVICE_START_PENDING ;
  175. ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 3000); // 处理第一个事件大约需要3秒钟;
  176. //////////////////////////////////////////////////////////////////////////
  177. // 开始初始化服务;
  178. g_hCtrlSvc = ::CreateEvent( NULL,TRUE, FALSE, _T("CtrlService::g_hCtrlSvc"));
  179. if (g_hCtrlSvc == NULL)
  180. {
  181. // 向SCM报告服务已停止;
  182. ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0, 1, 0);
  183. return;
  184. }
  185. // 向SCM报告服务正在运行;
  186. ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
  187. // 开启工作者;
  188. if ( g_lpStartWorkCallBack )
  189. g_lpStartWorkCallBack();
  190. // 线程中的处理函数运行结束后返回ServiceMain(),
  191. // ServiceMain()调用WaitForSingleObject,
  192. // 因为服务被停止之前ServiceMain()不会结束
  193. WaitForSingleObject(g_hCtrlSvc,INFINITE); // INFINITE表示无限等待,等待SCM的信号;
  194. CloseHandle(g_hCtrlSvc);
  195. // 结束工作者;
  196. if ( g_lpEndofWorkCallBack )
  197. g_lpEndofWorkCallBack();
  198. SvcReportEvent(_T("Service stopped"));
  199. // 向SCM报告服务已停止工作;
  200. ReportSvcStatus(SERVICE_STOPPED,NO_ERROR,0,0,0);
  201. }
  202. /************************************************************************/
  203. /* 函数:SvcCtrlHandler;
  204. /* 描述:每当有控制码发送给服务时被SCM调用;
  205. /* 参数:;
  206. /* [IN] dwControlCode:发送给服务的控制码;
  207. /* [OUT] :;
  208. /* [IN/OUT] :;
  209. /* 返回:void;
  210. /* 注意:;
  211. /* 示例:;
  212. /*
  213. /* 修改:;
  214. /* 日期:;
  215. /* 内容:;
  216. /************************************************************************/
  217. void WINAPI SvcCtrlHandler(IN DWORD dwControlCode)
  218. {
  219. BOOL bsucc = FALSE;
  220. switch (dwControlCode)
  221. {
  222. case SERVICE_CONTROL_SHUTDOWN: // 关掉服务;
  223. case SERVICE_CONTROL_STOP: // 停止服务;
  224. bsucc = ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 0);
  225. if (bsucc)
  226. KillService();
  227. break;
  228. case SERVICE_CONTROL_PAUSE:
  229. // 暂停服务;
  230. break;
  231. case SERVICE_CONTROL_CONTINUE:
  232. // 恢复被暂停的服务;
  233. break;
  234. case SERVICE_CONTROL_INTERROGATE:
  235. break;
  236. default:
  237. SvcReportEvent(_T("Bad service request"));
  238. }
  239. }
  240. /************************************************************************/
  241. /* 函数:ReportSvcStatus;
  242. /* 描述:设置当前服务状态,并将其报告给SCM;
  243. /* 参数:;
  244. /* [IN] dwCurrentState:服务当前状态(详情见 SERVICE_STATUS);
  245. /* [IN] dwWin32ExitCode:系统返回服务的错误码;
  246. /* [IN] dwServiceSpecificExitCode:用户自定义的服务错误码;
  247. /* [OUT] dwCheckPoint:;
  248. /* [IN/OUT] dwWaitHint:挂起操作的估计用时;
  249. /* 返回:void;
  250. /* 注意:;
  251. /* 示例:;
  252. /*
  253. /* 修改:;
  254. /* 日期:;
  255. /* 内容:;
  256. /************************************************************************/
  257. BOOL ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint)
  258. {
  259. BOOL bSuccess;
  260. // 填充SERVICE_STATUS结构体,以便用于设置服务状态;
  261. g_SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; // 表示我们的服务是独占一个进程的服务 ;
  262. g_SvcStatus.dwCurrentState = dwCurrentState; // 当前服务状态;
  263. g_SvcStatus.dwWaitHint = dwWaitHint;
  264. if( dwCurrentState == SERVICE_START_PENDING )
  265. {
  266. g_SvcStatus.dwControlsAccepted = 0; // 不接受任何控制通知;
  267. }
  268. else
  269. {
  270. // 通知 SCM 服务接受哪个控制通知:这里允许停止、关机、暂停继续;
  271. g_SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ; //|SERVICE_ACCEPT_PAUSE_CONTINUE;
  272. }
  273. if ( (dwCurrentState == SERVICE_RUNNING ) || ( dwCurrentState == SERVICE_STOPPED ) )
  274. g_SvcStatus.dwCheckPoint = 0;
  275. else
  276. g_SvcStatus.dwCheckPoint = dwCheckPoint++;
  277. // dwServiceSpecificExitCode在你终止服务并报告退出细节时很有用。
  278. // 初始化服务时并不退出,因此值为 0;
  279. if(dwServiceSpecificExitCode == 0)
  280. {
  281. g_SvcStatus.dwWin32ExitCode = dwWin32ExitCode;
  282. }
  283. else
  284. {
  285. g_SvcStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; //用户自定义错误代码;
  286. }
  287. g_SvcStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
  288. //设置好nServiceStatus后,向SCM报告服务状态,非0表示成功,0表示失败;
  289. bSuccess = SetServiceStatus( g_SvcStatusHandle,&g_SvcStatus);
  290. if( !bSuccess )
  291. {
  292. SvcReportEvent(_T("Set Service Status failed (%d) "), GetLastError());
  293. KillService();
  294. return FALSE;
  295. }
  296. else
  297. return TRUE;
  298. }
  299. // 结束服务;
  300. void KillService()
  301. {
  302. //LOG4C((LOG_NOTICE,"KillService."));
  303. SetEvent(g_hCtrlSvc); //如果操作成功,则返回非零值,否则为0。设置事件的状态为有标记,释放任意等待线程。如果事件是手工的,此事件将保持有标记直到调用ResetEvent。这种情况下将释放多个线程,如果事件是自动的,此事件将保持有标记,直到一个线程被释放,系统将设置事件的状态为无标记。如果没有线程在等待,则此事件将保持有标记,直到一个线程被释放。
  304. //ReportStatusToSCMgr(SERVICE_STOPPED,NO_ERROR,0,0,0);
  305. }
  306. /************************************************************************/
  307. /* 函数:;
  308. /* 描述:;
  309. /* 参数:;
  310. /* [IN] :;
  311. /* [OUT] :;
  312. /* [IN/OUT] :;
  313. /* 返回:void;
  314. /* 注意:;
  315. /* 示例:;
  316. /*
  317. /* 修改:;
  318. /* 日期:;
  319. /* 内容:;
  320. /************************************************************************/
  321. void SvcReportEvent(IN LPCTSTR pFormat, ...)
  322. {
  323. TCHAR szReport[MAX_PATH] = {0};
  324. HANDLE hEventSource;
  325. LPCTSTR lpszStrings[2];
  326. va_list pArg = NULL;
  327. va_start(pArg, pFormat);
  328. StringCchVPrintf(szReport, MAX_PATH, pFormat, pArg);
  329. va_end(pArg);
  330. hEventSource = RegisterEventSource(NULL, g_szSvcName);
  331. if (hEventSource != NULL)
  332. {
  333. lpszStrings[0] = g_szSvcName;
  334. lpszStrings[1] = szReport;
  335. ReportEvent(
  336. hEventSource, // 事件日志句柄;
  337. EVENTLOG_INFORMATION_TYPE, // 事件类型;
  338. 0, // 事件类别;
  339. 0/*SVC_ERROR*/, // 事件标识;
  340. NULL, // 无安全标识;
  341. 2, // lpszStrings数组大小;
  342. 0, // 无二进制数据;
  343. lpszStrings, // 字符串数组;
  344. NULL // 无二进制数据;
  345. );
  346. DeregisterEventSource(hEventSource);
  347. }
  348. }
  349. /************************************************************************/
  350. /* 函数:StartSvc;
  351. /* 描述:启动服务;
  352. /* 参数:;
  353. /* [IN] lpSvcName:要打开的服务名称;
  354. /* 返回:void;
  355. /* 注意:;
  356. /* 示例:;
  357. /*
  358. /* 修改:;
  359. /* 日期:;
  360. /* 内容:;
  361. /************************************************************************/
  362. void StartSvc(IN LPCTSTR lpSvcName)
  363. {
  364. if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
  365. {
  366. _tprintf_s(_T("要启动的服务名空\n"));
  367. return;
  368. }
  369. SC_HANDLE schSCM;
  370. SC_HANDLE schService;
  371. SERVICE_STATUS_PROCESS ssStatus;
  372. DWORD dwOldCheckPoint;
  373. DWORD dwStartTickCount;
  374. DWORD dwWaitTime;
  375. DWORD dwBytesNeeded;
  376. // 打开服务管理器;
  377. schSCM = OpenSCManager(
  378. NULL, // NULL表示要地计算机;
  379. NULL, // NULl表示服务活动数据库;
  380. SC_MANAGER_ALL_ACCESS); // 全部管理权限;
  381. if (NULL == schSCM)
  382. {
  383. _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
  384. return;
  385. }
  386. // 获取服务句柄;
  387. schService = OpenService(
  388. schSCM, // SCM数据库;
  389. lpSvcName, // 服务名称;
  390. SERVICE_ALL_ACCESS); // 全部权限;
  391. if (schService == NULL)
  392. {
  393. _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
  394. CloseServiceHandle(schSCM);
  395. return;
  396. }
  397. // 启动服务前,检查服务状态以防服务不是停止的状态;
  398. if (!QueryServiceStatusEx(
  399. schService, // 服务句柄;
  400. SC_STATUS_PROCESS_INFO, // 要查询的服务状态类型;
  401. (LPBYTE) &ssStatus, // 服务状态对象地址;
  402. sizeof(SERVICE_STATUS_PROCESS), // 结构体大小;
  403. &dwBytesNeeded ) ) // size needed if buffer is too small
  404. {
  405. _tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
  406. CloseServiceHandle(schService);
  407. CloseServiceHandle(schSCM);
  408. return;
  409. }
  410. // Check if the service is already running. It would be possible
  411. // to stop the service here, but for simplicity this example just returns.
  412. // 如果服务已经在运行,检查;可以在这里停止服务,简单起见,这里只返回;
  413. if(ssStatus.dwCurrentState != SERVICE_STOPPED && ssStatus.dwCurrentState != SERVICE_STOP_PENDING)
  414. {
  415. _tprintf_s(_T("Cannot start the service because it is already running\n"));
  416. CloseServiceHandle(schService);
  417. CloseServiceHandle(schSCM);
  418. return;
  419. }
  420. // Save the tick count and initial checkpoint.
  421. // 保持计数值并初始化检查点;
  422. dwStartTickCount = GetTickCount();
  423. dwOldCheckPoint = ssStatus.dwCheckPoint;
  424. // Wait for the service to stop before attempting to start it.
  425. // 在尝试启动服务前,等待服务停止;
  426. while (ssStatus.dwCurrentState == SERVICE_STOP_PENDING)
  427. {
  428. // Do not wait longer than the wait hint. A good interval is
  429. // one-tenth of the wait hint but not less than 1 second
  430. // and not more than 10 seconds.
  431. dwWaitTime = ssStatus.dwWaitHint / 10;
  432. if( dwWaitTime < 1000 )
  433. dwWaitTime = 1000;
  434. else if ( dwWaitTime > 10000 )
  435. dwWaitTime = 10000;
  436. Sleep( dwWaitTime );
  437. // Check the status until the service is no longer stop pending.
  438. // 检测状态直到服务不再停止等待;
  439. if (!QueryServiceStatusEx(
  440. schService, // handle to service
  441. SC_STATUS_PROCESS_INFO, // information level
  442. (LPBYTE) &ssStatus, // address of structure
  443. sizeof(SERVICE_STATUS_PROCESS), // size of structure
  444. &dwBytesNeeded ) ) // size needed if buffer is too small
  445. {
  446. _tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
  447. CloseServiceHandle(schService);
  448. CloseServiceHandle(schSCM);
  449. return;
  450. }
  451. if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
  452. {
  453. // Continue to wait and check.
  454. // 继续等待并检测;
  455. dwStartTickCount = GetTickCount();
  456. dwOldCheckPoint = ssStatus.dwCheckPoint;
  457. }
  458. else
  459. {
  460. if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
  461. {
  462. _tprintf_s(_T("Timeout waiting for service to stop\n"));
  463. CloseServiceHandle(schService);
  464. CloseServiceHandle(schSCM);
  465. return;
  466. }
  467. }
  468. }
  469. // Attempt to start the service.
  470. // 尝试启动服务;
  471. if (!StartService(
  472. schService, // handle to service
  473. 0, // number of arguments
  474. NULL) ) // no arguments
  475. {
  476. _tprintf_s(_T("StartService failed (%d)\n"), GetLastError());
  477. CloseServiceHandle(schService);
  478. CloseServiceHandle(schSCM);
  479. return;
  480. }
  481. else printf("Service start pending...\n");
  482. // Check the status until the service is no longer start pending.
  483. // 检测服务状态直到服务不再启动挂起操作;
  484. if (!QueryServiceStatusEx(
  485. schService, // handle to service
  486. SC_STATUS_PROCESS_INFO, // info level
  487. (LPBYTE) &ssStatus, // address of structure
  488. sizeof(SERVICE_STATUS_PROCESS), // size of structure
  489. &dwBytesNeeded ) ) // if buffer too small
  490. {
  491. _tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
  492. CloseServiceHandle(schService);
  493. CloseServiceHandle(schSCM);
  494. return;
  495. }
  496. // Save the tick count and initial checkpoint.
  497. dwStartTickCount = GetTickCount();
  498. dwOldCheckPoint = ssStatus.dwCheckPoint;
  499. while (ssStatus.dwCurrentState == SERVICE_START_PENDING)
  500. {
  501. // Do not wait longer than the wait hint. A good interval is
  502. // one-tenth the wait hint, but no less than 1 second and no
  503. // more than 10 seconds.
  504. dwWaitTime = ssStatus.dwWaitHint / 10;
  505. if( dwWaitTime < 1000 )
  506. dwWaitTime = 1000;
  507. else if ( dwWaitTime > 10000 )
  508. dwWaitTime = 10000;
  509. Sleep( dwWaitTime );
  510. // Check the status again.
  511. if (!QueryServiceStatusEx(
  512. schService, // handle to service
  513. SC_STATUS_PROCESS_INFO, // info level
  514. (LPBYTE) &ssStatus, // address of structure
  515. sizeof(SERVICE_STATUS_PROCESS), // size of structure
  516. &dwBytesNeeded ) ) // if buffer too small
  517. {
  518. _tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
  519. break;
  520. }
  521. if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
  522. {
  523. // Continue to wait and check.
  524. dwStartTickCount = GetTickCount();
  525. dwOldCheckPoint = ssStatus.dwCheckPoint;
  526. }
  527. else
  528. {
  529. if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
  530. {
  531. // No progress made within the wait hint.
  532. break;
  533. }
  534. }
  535. }
  536. // Determine whether the service is running.
  537. if (ssStatus.dwCurrentState == SERVICE_RUNNING)
  538. {
  539. _tprintf_s(_T("Service started successfully.\n"));
  540. }
  541. else
  542. {
  543. _tprintf_s(_T("Service not started. \n"));
  544. _tprintf_s(_T(" Current State: %d\n"), ssStatus.dwCurrentState);
  545. _tprintf_s(_T(" Exit Code: %d\n"), ssStatus.dwWin32ExitCode);
  546. _tprintf_s(_T(" Check Point: %d\n"), ssStatus.dwCheckPoint);
  547. _tprintf_s(_T(" Wait Hint: %d\n"), ssStatus.dwWaitHint);
  548. }
  549. CloseServiceHandle(schService);
  550. CloseServiceHandle(schSCM);
  551. }
  552. /************************************************************************/
  553. /* 函数:UpdateSvcDacl;
  554. /* 描述:;
  555. /* 参数:;
  556. /* [IN] :;
  557. /* [OUT] :;
  558. /* [IN/OUT] :;
  559. /* 返回:void;
  560. /* 注意:;
  561. /* 示例:;
  562. /*
  563. /* 修改:;
  564. /* 日期:;
  565. /* 内容:;
  566. /************************************************************************/
  567. void UpdateSvcDacl(IN LPCTSTR lpSvcName)
  568. {
  569. if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
  570. return;
  571. EXPLICIT_ACCESS ea;
  572. SECURITY_DESCRIPTOR sd;
  573. PSECURITY_DESCRIPTOR psd = NULL;
  574. PACL pacl = NULL;
  575. PACL pNewAcl = NULL;
  576. BOOL bDaclPresent = FALSE;
  577. BOOL bDaclDefaulted = FALSE;
  578. DWORD dwError = 0;
  579. DWORD dwSize = 0;
  580. DWORD dwBytesNeeded = 0;
  581. SC_HANDLE schSCManager;
  582. SC_HANDLE schService;
  583. // 获取SCM数据库的句柄值;
  584. schSCManager = OpenSCManager(
  585. NULL, // local computer
  586. NULL, // ServicesActive database
  587. SC_MANAGER_ALL_ACCESS); // full access rights
  588. if (NULL == schSCManager)
  589. {
  590. _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
  591. return;
  592. }
  593. // Get a handle to the service
  594. schService = OpenService(
  595. schSCManager, // SCManager database
  596. lpSvcName, // name of service
  597. READ_CONTROL | WRITE_DAC); // access
  598. if (schService == NULL)
  599. {
  600. _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
  601. CloseServiceHandle(schSCManager);
  602. return;
  603. }
  604. // Get the current security descriptor.
  605. // 获取当前服务的安全描述符;
  606. if (!QueryServiceObjectSecurity(schService,
  607. DACL_SECURITY_INFORMATION,
  608. &psd, // using NULL does not work on all versions
  609. 0,
  610. &dwBytesNeeded))
  611. {
  612. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  613. {
  614. dwSize = dwBytesNeeded;
  615. psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
  616. if (psd == NULL)
  617. {
  618. // Note: HeapAlloc does not support GetLastError.
  619. _tprintf_s(_T("HeapAlloc failed\n"));
  620. goto dacl_cleanup;
  621. }
  622. if (!QueryServiceObjectSecurity(schService,
  623. DACL_SECURITY_INFORMATION, psd, dwSize, &dwBytesNeeded))
  624. {
  625. _tprintf_s(_T("QueryServiceObjectSecurity failed (%d)\n"), GetLastError());
  626. goto dacl_cleanup;
  627. }
  628. }
  629. else
  630. {
  631. _tprintf_s(_T("QueryServiceObjectSecurity failed (%d)\n"), GetLastError());
  632. goto dacl_cleanup;
  633. }
  634. }
  635. // Get the DACL.
  636. if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl,
  637. &bDaclDefaulted))
  638. {
  639. _tprintf_s(_T("GetSecurityDescriptorDacl failed(%d)\n"), GetLastError());
  640. goto dacl_cleanup;
  641. }
  642. // Build the ACE.
  643. BuildExplicitAccessWithName(&ea, TEXT("GUEST"),
  644. SERVICE_START | SERVICE_STOP | READ_CONTROL | DELETE,
  645. SET_ACCESS, NO_INHERITANCE);
  646. dwError = SetEntriesInAcl(1, &ea, pacl, &pNewAcl);
  647. if (dwError != ERROR_SUCCESS)
  648. {
  649. printf("SetEntriesInAcl failed(%d)\n", dwError);
  650. goto dacl_cleanup;
  651. }
  652. // Initialize a new security descriptor.
  653. if (!InitializeSecurityDescriptor(&sd,
  654. SECURITY_DESCRIPTOR_REVISION))
  655. {
  656. printf("InitializeSecurityDescriptor failed(%d)\n", GetLastError());
  657. goto dacl_cleanup;
  658. }
  659. // Set the new DACL in the security descriptor.
  660. if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE))
  661. {
  662. printf("SetSecurityDescriptorDacl failed(%d)\n", GetLastError());
  663. goto dacl_cleanup;
  664. }
  665. // Set the new DACL for the service object.
  666. if (!SetServiceObjectSecurity(schService,
  667. DACL_SECURITY_INFORMATION, &sd))
  668. {
  669. printf("SetServiceObjectSecurity failed(%d)\n", GetLastError());
  670. goto dacl_cleanup;
  671. }
  672. else printf("Service DACL updated successfully\n");
  673. dacl_cleanup:
  674. CloseServiceHandle(schSCManager);
  675. CloseServiceHandle(schService);
  676. if(NULL != pNewAcl)
  677. LocalFree((HLOCAL)pNewAcl);
  678. if(NULL != psd)
  679. HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
  680. }
  681. void DoStopSvc(IN LPCTSTR lpSvcName)
  682. {
  683. if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
  684. {
  685. _tprintf_s(_T("指定要停止的服务名无效\n"));
  686. return;
  687. }
  688. SERVICE_STATUS_PROCESS ssp;
  689. DWORD dwStartTime = GetTickCount();
  690. DWORD dwBytesNeeded;
  691. DWORD dwTimeout = 30000; // 30-second time-out
  692. DWORD dwWaitTime;
  693. SC_HANDLE schSCManager;
  694. SC_HANDLE schService;
  695. // Get a handle to the SCM database.
  696. schSCManager = OpenSCManager(
  697. NULL, // local computer
  698. NULL, // ServicesActive database
  699. SC_MANAGER_ALL_ACCESS); // full access rights
  700. if (NULL == schSCManager)
  701. {
  702. printf("OpenSCManager failed (%d)\n", GetLastError());
  703. return;
  704. }
  705. // Get a handle to the service.
  706. schService = OpenService(
  707. schSCManager, // SCM database
  708. lpSvcName, // name of service
  709. SERVICE_STOP |
  710. SERVICE_QUERY_STATUS |
  711. SERVICE_ENUMERATE_DEPENDENTS);
  712. if (schService == NULL)
  713. {
  714. printf("OpenService failed (%d)\n", GetLastError());
  715. CloseServiceHandle(schSCManager);
  716. return;
  717. }
  718. // Make sure the service is not already stopped.
  719. if ( !QueryServiceStatusEx(
  720. schService,
  721. SC_STATUS_PROCESS_INFO,
  722. (LPBYTE)&ssp,
  723. sizeof(SERVICE_STATUS_PROCESS),
  724. &dwBytesNeeded ) )
  725. {
  726. printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
  727. goto stop_cleanup;
  728. }
  729. if ( ssp.dwCurrentState == SERVICE_STOPPED )
  730. {
  731. printf("Service is already stopped.\n");
  732. goto stop_cleanup;
  733. }
  734. // If a stop is pending, wait for it.
  735. while ( ssp.dwCurrentState == SERVICE_STOP_PENDING )
  736. {
  737. printf("Service stop pending...\n");
  738. // Do not wait longer than the wait hint. A good interval is
  739. // one-tenth of the wait hint but not less than 1 second
  740. // and not more than 10 seconds.
  741. dwWaitTime = ssp.dwWaitHint / 10;
  742. if( dwWaitTime < 1000 )
  743. dwWaitTime = 1000;
  744. else if ( dwWaitTime > 10000 )
  745. dwWaitTime = 10000;
  746. Sleep( dwWaitTime );
  747. if ( !QueryServiceStatusEx(
  748. schService,
  749. SC_STATUS_PROCESS_INFO,
  750. (LPBYTE)&ssp,
  751. sizeof(SERVICE_STATUS_PROCESS),
  752. &dwBytesNeeded ) )
  753. {
  754. printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
  755. goto stop_cleanup;
  756. }
  757. if ( ssp.dwCurrentState == SERVICE_STOPPED )
  758. {
  759. printf("Service stopped successfully.\n");
  760. goto stop_cleanup;
  761. }
  762. if ( GetTickCount() - dwStartTime > dwTimeout )
  763. {
  764. printf("Service stop timed out.\n");
  765. goto stop_cleanup;
  766. }
  767. }
  768. // If the service is running, dependencies must be stopped first.
  769. StopDependentServices();
  770. // Send a stop code to the service.
  771. if ( !ControlService(
  772. schService,
  773. SERVICE_CONTROL_STOP,
  774. (LPSERVICE_STATUS) &ssp ) )
  775. {
  776. printf( "ControlService failed (%d)\n", GetLastError() );
  777. goto stop_cleanup;
  778. }
  779. // Wait for the service to stop.
  780. while ( ssp.dwCurrentState != SERVICE_STOPPED )
  781. {
  782. Sleep( ssp.dwWaitHint );
  783. if ( !QueryServiceStatusEx(
  784. schService,
  785. SC_STATUS_PROCESS_INFO,
  786. (LPBYTE)&ssp,
  787. sizeof(SERVICE_STATUS_PROCESS),
  788. &dwBytesNeeded ) )
  789. {
  790. printf( "QueryServiceStatusEx failed (%d)\n", GetLastError() );
  791. goto stop_cleanup;
  792. }
  793. if ( ssp.dwCurrentState == SERVICE_STOPPED )
  794. break;
  795. if ( GetTickCount() - dwStartTime > dwTimeout )
  796. {
  797. printf( "Wait timed out\n" );
  798. goto stop_cleanup;
  799. }
  800. }
  801. printf("Service stopped successfully\n");
  802. stop_cleanup:
  803. CloseServiceHandle(schService);
  804. CloseServiceHandle(schSCManager);
  805. }
  806. BOOL StopDependentServices()
  807. {
  808. DWORD i;
  809. DWORD dwBytesNeeded;
  810. DWORD dwCount;
  811. LPENUM_SERVICE_STATUS lpDependencies = NULL;
  812. ENUM_SERVICE_STATUS ess;
  813. SC_HANDLE hDepService;
  814. SERVICE_STATUS_PROCESS ssp;
  815. DWORD dwStartTime = GetTickCount();
  816. DWORD dwTimeout = 30000; // 30-second time-out
  817. SC_HANDLE schSCManager = NULL;
  818. SC_HANDLE schService = NULL;
  819. // Pass a zero-length buffer to get the required buffer size.
  820. if ( EnumDependentServices( schService, SERVICE_ACTIVE,
  821. lpDependencies, 0, &dwBytesNeeded, &dwCount ) )
  822. {
  823. // If the Enum call succeeds, then there are no dependent
  824. // services, so do nothing.
  825. return TRUE;
  826. }
  827. else
  828. {
  829. if ( GetLastError() != ERROR_MORE_DATA )
  830. return FALSE; // Unexpected error
  831. // Allocate a buffer for the dependencies.
  832. lpDependencies = (LPENUM_SERVICE_STATUS) HeapAlloc(
  833. GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded );
  834. if ( !lpDependencies )
  835. return FALSE;
  836. __try {
  837. // Enumerate the dependencies.
  838. if ( !EnumDependentServices( schService, SERVICE_ACTIVE,
  839. lpDependencies, dwBytesNeeded, &dwBytesNeeded,
  840. &dwCount ) )
  841. return FALSE;
  842. for ( i = 0; i < dwCount; i++ )
  843. {
  844. ess = *(lpDependencies + i);
  845. // Open the service.
  846. hDepService = OpenService( schSCManager,
  847. ess.lpServiceName,
  848. SERVICE_STOP | SERVICE_QUERY_STATUS );
  849. if ( !hDepService )
  850. return FALSE;
  851. __try {
  852. // Send a stop code.
  853. if ( !ControlService( hDepService,
  854. SERVICE_CONTROL_STOP,
  855. (LPSERVICE_STATUS) &ssp ) )
  856. return FALSE;
  857. // Wait for the service to stop.
  858. while ( ssp.dwCurrentState != SERVICE_STOPPED )
  859. {
  860. Sleep( ssp.dwWaitHint );
  861. if ( !QueryServiceStatusEx(
  862. hDepService,
  863. SC_STATUS_PROCESS_INFO,
  864. (LPBYTE)&ssp,
  865. sizeof(SERVICE_STATUS_PROCESS),
  866. &dwBytesNeeded ) )
  867. return FALSE;
  868. if ( ssp.dwCurrentState == SERVICE_STOPPED )
  869. break;
  870. if ( GetTickCount() - dwStartTime > dwTimeout )
  871. return FALSE;
  872. }
  873. }
  874. __finally
  875. {
  876. // Always release the service handle.
  877. CloseServiceHandle( hDepService );
  878. }
  879. }
  880. }
  881. __finally
  882. {
  883. // Always free the enumeration buffer.
  884. HeapFree( GetProcessHeap(), 0, lpDependencies );
  885. }
  886. }
  887. return TRUE;
  888. }
  889. /************************************************************************/
  890. /* 函数:;
  891. /* 描述:;
  892. /* 参数:;
  893. /* [IN] :;
  894. /* [OUT] :;
  895. /* [IN/OUT] :;
  896. /* 返回:void;
  897. /* 注意:;
  898. /* 示例:;
  899. /*
  900. /* 修改:;
  901. /* 日期:;
  902. /* 内容:;
  903. /************************************************************************/
  904. void DoQuerySvc(IN LPCTSTR lpSvcName)
  905. {
  906. if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
  907. {
  908. _tprintf_s(_T("要查询的服务名称无效\n"));
  909. return;
  910. }
  911. SC_HANDLE hSCM;
  912. SC_HANDLE hSvc;
  913. LPQUERY_SERVICE_CONFIG lpsc;
  914. LPSERVICE_DESCRIPTION lpsd;
  915. DWORD dwBytesNeeded, cbBfuSize, dwError;
  916. // 获取SCM句柄;
  917. hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
  918. if ( hSCM == NULL )
  919. {
  920. _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
  921. return;
  922. }
  923. // 获取服务句柄;
  924. hSvc = OpenService(
  925. hSCM,
  926. lpSvcName,
  927. SERVICE_QUERY_CONFIG // 需要查询设置的权限;
  928. );
  929. if ( hSvc == NULL )
  930. {
  931. _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
  932. CloseServiceHandle(hSCM);
  933. return;
  934. }
  935. // 获取服务设置信息;
  936. if ( !QueryServiceConfig( hSvc, NULL, 0, &dwBytesNeeded) )
  937. {
  938. dwError = GetLastError();
  939. if ( ERROR_INSUFFICIENT_BUFFER == dwError )
  940. {
  941. cbBfuSize = dwBytesNeeded;
  942. lpsc = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LMEM_FIXED, cbBfuSize);
  943. }
  944. else
  945. {
  946. _tprintf_s(_T("QueryServiceConfig failed (%d)\n"), dwError);
  947. goto cleanup;
  948. }
  949. }
  950. if ( !QueryServiceConfig(hSvc, lpsc, cbBfuSize, &dwBytesNeeded) )
  951. {
  952. _tprintf_s(_T("QuerySericeConfig failed (%d)\n"), GetLastError());
  953. goto cleanup;
  954. }
  955. if ( !QueryServiceConfig2( hSvc, SERVICE_CONFIG_DESCRIPTION, NULL, 0, &dwBytesNeeded) )
  956. {
  957. dwError = GetLastError();
  958. if ( ERROR_INSUFFICIENT_BUFFER == dwError )
  959. {
  960. cbBfuSize = dwBytesNeeded;
  961. lpsd = (LPSERVICE_DESCRIPTION)LocalAlloc(LMEM_FIXED, cbBfuSize);
  962. }
  963. else
  964. {
  965. _tprintf_s(_T("QuerySericeConfig2 failed (%d)\n"), GetLastError());
  966. goto cleanup;
  967. }
  968. }
  969. if ( !QueryServiceConfig2( hSvc, SERVICE_CONFIG_DESCRIPTION, (LPBYTE)lpsd, cbBfuSize, &dwBytesNeeded) )
  970. {
  971. _tprintf_s(_T("QuerySericeConfig2 failed (%d)\n"), GetLastError());
  972. goto cleanup;
  973. }
  974. //////////////////////////////////////////////////////////////////////////
  975. // 查询成功,组织要返回的东西;
  976. _tprintf(TEXT("%s configuration: \n"), g_szSvcName);
  977. _tprintf(TEXT(" Type: 0x%x\n"), lpsc->dwServiceType);
  978. _tprintf(TEXT(" Start Type: 0x%x\n"), lpsc->dwStartType);
  979. _tprintf(TEXT(" Error Control: 0x%x\n"), lpsc->dwErrorControl);
  980. _tprintf(TEXT(" Binary path: %s\n"), lpsc->lpBinaryPathName);
  981. _tprintf(TEXT(" Account: %s\n"), lpsc->lpServiceStartName);
  982. if (lpsd->lpDescription != NULL && lstrcmp(lpsd->lpDescription, TEXT("")) != 0)
  983. _tprintf(TEXT(" Description: %s\n"), lpsd->lpDescription);
  984. if (lpsc->lpLoadOrderGroup != NULL && lstrcmp(lpsc->lpLoadOrderGroup, TEXT("")) != 0)
  985. _tprintf(TEXT(" Load order group: %s\n"), lpsc->lpLoadOrderGroup);
  986. if (lpsc->dwTagId != 0)
  987. _tprintf(TEXT(" Tag ID: %d\n"), lpsc->dwTagId);
  988. if (lpsc->lpDependencies != NULL && lstrcmp(lpsc->lpDependencies, TEXT("")) != 0)
  989. _tprintf(TEXT(" Dependencies: %s\n"), lpsc->lpDependencies);
  990. // 释放资源;
  991. LocalFree(lpsc);
  992. LocalFree(lpsd);
  993. cleanup:
  994. CloseServiceHandle(hSvc);
  995. CloseServiceHandle(hSCM);
  996. }
  997. /************************************************************************/
  998. /* 函数:;
  999. /* 描述:;
  1000. /* 参数:;
  1001. /* [IN] :;
  1002. /* [OUT] :;
  1003. /* [IN/OUT] :;
  1004. /* 返回:void;
  1005. /* 注意:;
  1006. /* 示例:;
  1007. /*
  1008. /* 修改:;
  1009. /* 日期:;
  1010. /* 内容:;
  1011. /************************************************************************/
  1012. void DoDisableSvc(IN LPCTSTR lpSvcName)
  1013. {
  1014. if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
  1015. {
  1016. _tprintf_s(_T("要禁用的服务名称无效\n"));
  1017. return;
  1018. }
  1019. SC_HANDLE schSCM;
  1020. SC_HANDLE schSvc;
  1021. // 打开SCM;
  1022. schSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  1023. if ( schSCM == NULL )
  1024. {
  1025. _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
  1026. return;
  1027. }
  1028. // 获取服务句柄;
  1029. schSvc = OpenService(schSCM, lpSvcName, SERVICE_CHANGE_CONFIG );
  1030. if ( schSvc == NULL )
  1031. {
  1032. _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
  1033. CloseServiceHandle(schSCM);
  1034. return;
  1035. }
  1036. if ( !ChangeServiceConfig(
  1037. schSvc,
  1038. SERVICE_NO_CHANGE, // service type: no change
  1039. SERVICE_DISABLED, // service start type
  1040. SERVICE_NO_CHANGE, // error control: no change
  1041. NULL, // binary path: no change
  1042. NULL, // load order group: no change
  1043. NULL, // tag ID: no change
  1044. NULL, // dependencies: no change
  1045. NULL, // account name: no change
  1046. NULL, // password: no change
  1047. NULL) ) // display name: no change
  1048. {
  1049. _tprintf_s(_T("ChangeServiceConfig failed (%d)\n"), GetLastError());
  1050. }
  1051. CloseServiceHandle(schSvc);
  1052. CloseServiceHandle(schSCM);
  1053. }
  1054. /************************************************************************/
  1055. /* 函数:;
  1056. /* 描述:;
  1057. /* 参数:;
  1058. /* [IN] :;
  1059. /* [OUT] :;
  1060. /* [IN/OUT] :;
  1061. /* 返回:void;
  1062. /* 注意:;
  1063. /* 示例:;
  1064. /*
  1065. /* 修改:;
  1066. /* 日期:;
  1067. /* 内容:;
  1068. /************************************************************************/
  1069. void DoEnableSvc(IN LPCTSTR lpSvcName)
  1070. {
  1071. if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
  1072. {
  1073. _tprintf_s(_T("要启用的服务名称无效\n"));
  1074. return;
  1075. }
  1076. SC_HANDLE schSCM;
  1077. SC_HANDLE schSvc;
  1078. // Get a handle to the SCM database.
  1079. // 获取SCM数据库句柄;
  1080. schSCM = OpenSCManager(
  1081. NULL, // local computer
  1082. NULL, // ServicesActive database
  1083. SC_MANAGER_ALL_ACCESS); // full access rights
  1084. if (NULL == schSCM)
  1085. {
  1086. printf("OpenSCManager failed (%d)\n", GetLastError());
  1087. return;
  1088. }
  1089. // Get a handle to the service.
  1090. // 获取服务句柄值;
  1091. schSvc = OpenService(
  1092. schSCM, // SCM database
  1093. lpSvcName, // name of service
  1094. SERVICE_CHANGE_CONFIG); // need change config access
  1095. if (schSvc == NULL)
  1096. {
  1097. _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
  1098. CloseServiceHandle(schSCM);
  1099. return;
  1100. }
  1101. // Change the service start type.
  1102. // 改变服务启动类型;
  1103. if (! ChangeServiceConfig(
  1104. schSvc, // 服务句柄;
  1105. SERVICE_NO_CHANGE, // service type: no change
  1106. SERVICE_DEMAND_START, // service start type
  1107. SERVICE_NO_CHANGE, // error control: no change
  1108. NULL, // binary path: no change
  1109. NULL, // load order group: no change
  1110. NULL, // tag ID: no change
  1111. NULL, // dependencies: no change
  1112. NULL, // account name: no change
  1113. NULL, // password: no change
  1114. NULL) ) // display name: no change
  1115. {
  1116. _tprintf_s(_T("ChangeServiceConfig failed (%d)\n"), GetLastError());
  1117. }
  1118. else
  1119. {
  1120. _tprintf_s(_T("Service enabled successfully.\n"));
  1121. }
  1122. CloseServiceHandle(schSvc);
  1123. CloseServiceHandle(schSCM);
  1124. }
  1125. /************************************************************************/
  1126. /* 函数:;
  1127. /* 描述:;
  1128. /* 参数:;
  1129. /* [IN] :;
  1130. /* [OUT] :;
  1131. /* [IN/OUT] :;
  1132. /* 返回:void;
  1133. /* 注意:;
  1134. /* 示例:;
  1135. /*
  1136. /* 修改:;
  1137. /* 日期:;
  1138. /* 内容:;
  1139. /************************************************************************/
  1140. void DoUpdateSvcDesc(IN LPCTSTR lpSvcName)
  1141. {
  1142. if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
  1143. {
  1144. _tprintf_s(_T("要更新描述的服务名称无效\n"));
  1145. return;
  1146. }
  1147. SC_HANDLE schSCM;
  1148. SC_HANDLE schSvc;
  1149. SERVICE_DESCRIPTION sd;
  1150. LPTSTR szDesc = TEXT("This is a test description");
  1151. // Get a handle to the SCM database.
  1152. // 获取SCM数据库句柄;
  1153. schSCM = OpenSCManager(
  1154. NULL, // NULL表示本地计算机;
  1155. NULL, // NULL表示:ServicesActive database
  1156. SC_MANAGER_ALL_ACCESS); // full access rights
  1157. if (NULL == schSCM)
  1158. {
  1159. _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
  1160. return;
  1161. }
  1162. // Get a handle to the service.
  1163. // 获取服务句柄值;
  1164. schSvc = OpenService(
  1165. schSCM, // SCM 数据库句柄;
  1166. lpSvcName, // 服务名称;
  1167. SERVICE_CHANGE_CONFIG); // need change config access
  1168. if (schSvc == NULL)
  1169. {
  1170. _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
  1171. CloseServiceHandle(schSCM);
  1172. return;
  1173. }
  1174. // Change the service description.
  1175. // 改变服务描述;
  1176. sd.lpDescription = szDesc;
  1177. if( !ChangeServiceConfig2(
  1178. schSvc, // 服务句柄;
  1179. SERVICE_CONFIG_DESCRIPTION, // 要改变的类型: description;
  1180. &sd) ) // 新描述;
  1181. {
  1182. _tprintf_s(_T("ChangeServiceConfig2 failed\n"));
  1183. }
  1184. else
  1185. {
  1186. _tprintf_s(_T("Service description updated successfully.\n"));
  1187. }
  1188. CloseServiceHandle(schSvc);
  1189. CloseServiceHandle(schSCM);
  1190. }
  1191. /************************************************************************/
  1192. /* 函数:;
  1193. /* 描述:;
  1194. /* 参数:;
  1195. /* [IN] :;
  1196. /* [OUT] :;
  1197. /* [IN/OUT] :;
  1198. /* 返回:void;
  1199. /* 注意:;
  1200. /* 示例:;
  1201. /*
  1202. /* 修改:;
  1203. /* 日期:;
  1204. /* 内容:;
  1205. /************************************************************************/
  1206. void DoDeleteSvc(IN LPCTSTR lpSvcName)
  1207. {
  1208. if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
  1209. {
  1210. _tprintf_s(_T("要删除的服务名称无效\n"));
  1211. return;
  1212. }
  1213. SC_HANDLE schSCM;
  1214. SC_HANDLE schSvc;
  1215. SERVICE_STATUS ssStatus;
  1216. // 打开服务管理器;
  1217. schSCM = OpenSCManager(
  1218. NULL, // NULL表示本地计算机;
  1219. NULL, // NULL表示ServicesActive database
  1220. SC_MANAGER_ALL_ACCESS); // full access rights
  1221. if (NULL == schSCM)
  1222. {
  1223. _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
  1224. return;
  1225. }
  1226. // 打开服务;
  1227. schSvc = OpenService(
  1228. schSCM, // SCM database
  1229. lpSvcName, // name of service
  1230. SERVICE_STOP|DELETE // need delete access
  1231. );
  1232. if (schSvc == NULL)
  1233. {
  1234. _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
  1235. CloseServiceHandle(schSCM);
  1236. return;
  1237. }
  1238. // 删除服务关,需要先停止服务;
  1239. if ( !::ControlService(schSvc, SERVICE_CONTROL_STOP, &ssStatus) )
  1240. {
  1241. _tprintf_s(_T("删除服务前停止服务失败 (%d)\n"), GetLastError());
  1242. }
  1243. // 删除服务;
  1244. if ( !DeleteService(schSvc) )
  1245. {
  1246. _tprintf_s(_T("DeleteService failed (%d)\n"), GetLastError());
  1247. SvcReportEvent(_T("Service could not be deleted"));
  1248. }
  1249. else
  1250. {
  1251. _tprintf_s(_T("Service deleted successfully\n"));
  1252. }
  1253. CloseServiceHandle(schSvc);
  1254. CloseServiceHandle(schSCM);
  1255. }
  1256. /************************************************************************/
  1257. /* 函数:SetCallBack;
  1258. /* 描述:设置回调函数;
  1259. /* 参数:;
  1260. /* [IN] lpStartWorkCallBack:工作开始回调指针;
  1261. /* [IN] lpEndofWorkCallBack:工作结束回调指针;
  1262. /* 返回:void;
  1263. /* 注意:;
  1264. /* 示例:;
  1265. /*
  1266. /* 修改:;
  1267. /* 日期:;
  1268. /* 内容:;
  1269. /************************************************************************/
  1270. void SetCallBack( IN LPVOID lpStartWorkCallBack, IN LPVOID lpEndofWorkCallBack )
  1271. {
  1272. if ( g_lpStartWorkCallBack == NULL )
  1273. g_lpStartWorkCallBack = (WorkEndofCallback)lpStartWorkCallBack;
  1274. if ( g_lpEndofWorkCallBack == NULL )
  1275. g_lpEndofWorkCallBack = (WorkEndofCallback)lpEndofWorkCallBack;
  1276. }
  1277. /************************************************************************/
  1278. /* 函数:StartProcess;
  1279. /* 描述:在服务进程里,调用外部EXE;
  1280. /* 参数:;
  1281. /* [IN] :;
  1282. /* [OUT] :;
  1283. /* [IN/OUT] :;
  1284. /* 返回:void;
  1285. /* 注意:;
  1286. /* 示例:;
  1287. /*
  1288. /* 修改:;
  1289. /* 日期:;
  1290. /* 内容:;
  1291. /************************************************************************/
  1292. BOOL StartProcess( IN LPCTSTR lpExePath )
  1293. {
  1294. #if 0
  1295. if( !lpExePath || !PathFileExists(lpExePath) )
  1296. {
  1297. return FALSE;
  1298. }
  1299. HANDLE hToken;
  1300. if(!GetTokenByName(hToken,_T("EXPLORER.EXE")))
  1301. {
  1302. return FALSE;
  1303. }
  1304. STARTUPINFO si;
  1305. PROCESS_INFORMATION pi;
  1306. ZeroMemory(&si, sizeof(STARTUPINFO));
  1307. si.cb = sizeof(STARTUPINFO);
  1308. si.lpDesktop = TEXT("winsta0\\default");
  1309. BOOL bResult = CreateProcessAsUser(hToken,lpExePath,NULL,NULL,NULL, FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);
  1310. DWORD dwError = GetLastError();// 返回740错误,表示服务必须在Admin账号下运行才能创建成功;
  1311. //CreateProcessWithTokenW(hToken, )
  1312. CloseHandle(hToken);
  1313. if(bResult)
  1314. {
  1315. // WriteLogAlways(_T("C:\\serverlog.txt"),_T("CreateProcessAsUser ok"));
  1316. }
  1317. else
  1318. {
  1319. //WriteLogAlways(_T("C:\\servererrlog.txt"),_T("CreateProcessAsUser failed"));
  1320. }
  1321. #else
  1322. HANDLE hPtoken = NULL ;
  1323. GetExplorerToken( &hPtoken ) ;
  1324. //if(!GetTokenByName(hPtoken,_T("EXPLORER.EXE")))
  1325. //{
  1326. // return FALSE;
  1327. //}
  1328. PROCESS_INFORMATION pi;
  1329. STARTUPINFOW si = { sizeof(STARTUPINFO),NULL,L"",NULL,0,0,0,0,0,0,0,STARTF_USESHOWWINDOW,0,0,NULL,0,0,0};
  1330. si.wShowWindow = SW_SHOW;
  1331. si.lpDesktop = NULL;
  1332. ZeroMemory( &pi, sizeof(pi) );
  1333. static HMODULE advapi32_dll = LoadLibraryW(L"advapi32.dll");
  1334. if(!advapi32_dll)
  1335. return FALSE;
  1336. /*static F_CreateProcessWithTokenW f_CreateProcessWithTokenW = (F_CreateProcessWithTokenW)(
  1337. GetProcAddress(advapi32_dll,"CreateProcessWithTokenW"));
  1338. if (f_CreateProcessWithTokenW == NULL)
  1339. return ;
  1340. */
  1341. BOOL bResult = CreateProcessWithTokenW(hPtoken, LOGON_WITH_PROFILE, NULL, (LPWSTR)lpExePath, NULL, NULL, NULL, &si,&pi);
  1342. DWORD dwError = GetLastError();
  1343. Sleep(1000);
  1344. CloseHandle( pi.hProcess );
  1345. CloseHandle( pi.hThread );
  1346. #endif
  1347. return bResult;
  1348. }
  1349. /************************************************************************/
  1350. /* 函数:;
  1351. /* 描述:;
  1352. /* 参数:;
  1353. /* [IN] :;
  1354. /* [OUT] :;
  1355. /* [IN/OUT] :;
  1356. /* 返回:void;
  1357. /* 注意:;
  1358. /* 示例:;
  1359. /*
  1360. /* 修改:;
  1361. /* 日期:;
  1362. /* 内容:;
  1363. /************************************************************************/
  1364. BOOL GetTokenByName( IN HANDLE &hToken, IN LPCTSTR lpName)
  1365. {
  1366. if(!lpName)
  1367. {
  1368. return FALSE;
  1369. }
  1370. BOOL bRet = FALSE;
  1371. HANDLE hProcessSnap = NULL;
  1372. PROCESSENTRY32 pe32 = {0};
  1373. hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  1374. if ( hProcessSnap == INVALID_HANDLE_VALUE )
  1375. return FALSE;
  1376. pe32.dwSize = sizeof(PROCESSENTRY32);
  1377. if (Process32First(hProcessSnap, &pe32))
  1378. {
  1379. do
  1380. {
  1381. CString exefile=pe32.szExeFile;
  1382. CString paraname = lpName;
  1383. if(!exefile.CompareNoCase(lpName))
  1384. {
  1385. HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
  1386. bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken);
  1387. CloseHandle( hProcessSnap );
  1388. return bRet;
  1389. }
  1390. }
  1391. while(Process32Next(hProcessSnap,&pe32));
  1392. bRet = TRUE;
  1393. }
  1394. else
  1395. bRet = FALSE;
  1396. CloseHandle(hProcessSnap);
  1397. return bRet;
  1398. }
  1399. /************************************************************************/
  1400. /* 函数:;
  1401. /* 描述:;
  1402. /* 参数:;
  1403. /* [IN] :;
  1404. /* [OUT] :;
  1405. /* [IN/OUT] :;
  1406. /* 返回:void;
  1407. /* 注意:;
  1408. /* 示例:;
  1409. /*
  1410. /* 修改:;
  1411. /* 日期:;
  1412. /* 内容:;
  1413. /************************************************************************/
  1414. // Jeff.Hacker. WINDOWS NT 以上的内核需要提权,才能对系统进行高级管理;
  1415. BOOL GetDebugPriv()
  1416. {
  1417. // 返回的访问令牌指针;
  1418. HANDLE hToken;
  1419. // 接收所返回的制定特权名称的信息;
  1420. LUID sedebugnameValue;
  1421. // 新特权信息的指针(结构体);
  1422. TOKEN_PRIVILEGES tkp;
  1423. DWORD dwCurProcId = GetCurrentProcessId();
  1424. // 要修改访问权限的进程句柄;
  1425. HANDLE hCurProc;
  1426. hCurProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwCurProcId);
  1427. if (!::OpenProcessToken(hCurProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
  1428. {
  1429. //ShowSystemErrorInfo(_T("升级包OpenProcessToken失败."),GetLastError());
  1430. return FALSE;
  1431. }
  1432. if (!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))
  1433. {
  1434. //ShowSystemErrorInfo(_T("升级包LookupPrivilegeValue失败."),GetLastError());
  1435. CloseHandle(hToken);
  1436. return FALSE;
  1437. }
  1438. tkp.PrivilegeCount = 1;
  1439. tkp.Privileges[0].Luid = sedebugnameValue;
  1440. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  1441. if (!::AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL))
  1442. {
  1443. //ShowSystemErrorInfo(_T("升级包AdjustTokenPrivileges失败."),GetLastError());
  1444. CloseHandle(hToken);
  1445. return FALSE;
  1446. }
  1447. CloseHandle(hCurProc);
  1448. CloseHandle(hToken);
  1449. return TRUE;
  1450. }
  1451. DWORD GetExplorerToken(OUT HANDLE* phExplorerToken)
  1452. {
  1453. DWORD dwStatus = ERROR_FILE_NOT_FOUND ;
  1454. BOOL bRet = FALSE ;
  1455. HANDLE hProcess = NULL ;
  1456. HANDLE hProcessSnap = NULL ;
  1457. TCHAR szExplorerPath[MAX_PATH] = { 0 };
  1458. TCHAR FileName[MAX_PATH] = { 0 };
  1459. PROCESSENTRY32 pe32 = { 0 } ;
  1460. __try
  1461. {
  1462. GetWindowsDirectory( szExplorerPath , MAX_PATH ) ;
  1463. _tcscat_s( szExplorerPath , MAX_PATH, _T("\\Explorer.EXE") ) ;
  1464. hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS , 0 ) ;
  1465. if( hProcessSnap == INVALID_HANDLE_VALUE )
  1466. {
  1467. dwStatus = GetLastError() ;
  1468. __leave ;
  1469. }
  1470. pe32.dwSize = sizeof( PROCESSENTRY32 ) ;
  1471. if( !Process32First( hProcessSnap, &pe32 ))
  1472. {
  1473. dwStatus = GetLastError() ;
  1474. __leave ;
  1475. }
  1476. int ii = 0;
  1477. do
  1478. {
  1479. hProcess = OpenProcess(PROCESS_ALL_ACCESS/*PROCESS_QUERY_INFORMATION*/, FALSE, pe32.th32ProcessID ) ;
  1480. if( NULL != hProcess )
  1481. {
  1482. ii++;
  1483. //if ( GetModuleFileNameEx(hProcess , NULL , FileName , MAX_PATH) )
  1484. //{
  1485. if( _tcsicmp( pe32.szExeFile , _T("Explorer.EXE") ) == 0 )
  1486. {
  1487. HANDLE hToken ;
  1488. if( OpenProcessToken( hProcess , TOKEN_DUPLICATE , &hToken ))
  1489. {
  1490. HANDLE hNewToken = NULL;
  1491. DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hNewToken);
  1492. * phExplorerToken = hNewToken ;
  1493. dwStatus = 0 ;
  1494. CloseHandle(hToken);
  1495. }
  1496. break ;
  1497. }
  1498. //}
  1499. CloseHandle ( hProcess ) ;
  1500. hProcess = NULL ;
  1501. }
  1502. } while( Process32Next( hProcessSnap, &pe32 )) ;
  1503. }
  1504. __finally
  1505. {
  1506. if( NULL != hProcess )
  1507. {
  1508. CloseHandle( hProcess ) ;
  1509. }
  1510. if( NULL != hProcessSnap )
  1511. {
  1512. CloseHandle ( hProcessSnap ) ;
  1513. }
  1514. }
  1515. return dwStatus ;
  1516. }
  1517. };