spsvc_main.cpp 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132
  1. #include "spsvc.h"
  2. #include <aclapi.h>
  3. #define ANOTHER_USERNAME "ClientUser"
  4. SERVICE_STATUS g_srv_status = {0};
  5. SERVICE_STATUS_HANDLE g_srv_status_handle = NULL;
  6. HANDLE g_srv_stop_event = INVALID_HANDLE_VALUE;
  7. HANDLE g_file_map = NULL;
  8. void WINAPI service_ctrl_handle(DWORD);
  9. bool __stdcall StopDependentServices(SC_HANDLE sch_mnr, SC_HANDLE sch_srv)
  10. {
  11. DWORD i;
  12. DWORD dwBytesNeeded;
  13. DWORD dwCount;
  14. LPENUM_SERVICE_STATUS lpDependencies = NULL;
  15. ENUM_SERVICE_STATUS ess;
  16. SC_HANDLE hDepService;
  17. SERVICE_STATUS_PROCESS ssp;
  18. DWORD dwStartTime = GetTickCount();
  19. DWORD dwTimeout = 30000; // 30-second time-out
  20. // Pass a zero-length buffer to get the required buffer size.
  21. if ( EnumDependentServices( sch_srv, SERVICE_ACTIVE,
  22. lpDependencies, 0, &dwBytesNeeded, &dwCount ) )
  23. {
  24. // If the Enum call succeeds, then there are no dependent
  25. // services, so do nothing.
  26. return true;
  27. }
  28. else
  29. {
  30. if ( GetLastError() != ERROR_MORE_DATA )
  31. return false; // Unexpected error
  32. // Allocate a buffer for the dependencies.
  33. lpDependencies = (LPENUM_SERVICE_STATUS) HeapAlloc(
  34. GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded );
  35. if ( !lpDependencies )
  36. return false;
  37. __try {
  38. // Enumerate the dependencies.
  39. if ( !EnumDependentServices( sch_srv, SERVICE_ACTIVE,
  40. lpDependencies, dwBytesNeeded, &dwBytesNeeded,
  41. &dwCount ) )
  42. return false;
  43. for ( i = 0; i < dwCount; i++ )
  44. {
  45. ess = *(lpDependencies + i);
  46. // Open the service.
  47. hDepService = OpenService( sch_mnr,
  48. ess.lpServiceName,
  49. SERVICE_STOP | SERVICE_QUERY_STATUS );
  50. if ( !hDepService )
  51. return false;
  52. __try {
  53. // Send a stop code.
  54. if ( !ControlService( hDepService,
  55. SERVICE_CONTROL_STOP,
  56. (LPSERVICE_STATUS) &ssp ) )
  57. return false;
  58. // Wait for the service to stop.
  59. while ( ssp.dwCurrentState != SERVICE_STOPPED )
  60. {
  61. Sleep( ssp.dwWaitHint );
  62. if ( !QueryServiceStatusEx(
  63. hDepService,
  64. SC_STATUS_PROCESS_INFO,
  65. (LPBYTE)&ssp,
  66. sizeof(SERVICE_STATUS_PROCESS),
  67. &dwBytesNeeded ) )
  68. return false;
  69. if ( ssp.dwCurrentState == SERVICE_STOPPED )
  70. break;
  71. if ( GetTickCount() - dwStartTime > dwTimeout )
  72. return false;
  73. }
  74. }
  75. __finally
  76. {
  77. // Always release the service handle.
  78. CloseServiceHandle( hDepService );
  79. }
  80. }
  81. }
  82. __finally
  83. {
  84. // Always free the enumeration buffer.
  85. HeapFree( GetProcessHeap(), 0, lpDependencies );
  86. }
  87. }
  88. return true;
  89. }
  90. bool ChangeServiceStatus(DWORD status, DWORD exitcode, DWORD wait)
  91. {
  92. static DWORD dwCheckPoint = 1;
  93. g_srv_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
  94. //g_srv_status.dwControlsAccepted = ac;
  95. g_srv_status.dwCurrentState = status;
  96. g_srv_status.dwWin32ExitCode = exitcode;
  97. g_srv_status.dwServiceSpecificExitCode = 0;
  98. //g_srv_status.dwCheckPoint = progress;
  99. g_srv_status.dwWaitHint = wait;
  100. if (status == SERVICE_START_PENDING) {
  101. g_srv_status.dwControlsAccepted = 0;
  102. }
  103. else {
  104. g_srv_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  105. }
  106. if ( (status == SERVICE_RUNNING) || (status == SERVICE_STOPPED) ) {
  107. g_srv_status.dwCheckPoint = 0;
  108. }
  109. else {
  110. g_srv_status.dwCheckPoint = dwCheckPoint++;
  111. }
  112. return !!SetServiceStatus(g_srv_status_handle, &g_srv_status);
  113. }
  114. bool IsDirExist(LPCSTR lpDirPath)
  115. {
  116. DWORD dwRet = GetFileAttributesA(lpDirPath);
  117. return (dwRet != INVALID_FILE_ATTRIBUTES) && (dwRet & FILE_ATTRIBUTE_DIRECTORY);
  118. }
  119. void InitLogConfig()
  120. {
  121. if(IsDirExist("D:\\rvc\\dbg")) {
  122. GET_LOGGER()->SetFileWriteMode(Day_Seperated_Mode, "D:\\rvc\\dbg\\wFreeWrapSvc");
  123. } else if(IsDirExist("C:\\rvc\\dbg")) {
  124. GET_LOGGER()->SetFileWriteMode(Day_Seperated_Mode, "C:\\rvc\\dbg\\wFreeWrapSvc");
  125. } else {
  126. GET_LOGGER()->DisableRecord();
  127. }
  128. }
  129. bool GetCurrentUserToken(HANDLE& token, DWORD& sessionID, LPCTSTR lpcszUserName)
  130. {
  131. sessionID = -1;
  132. HANDLE cur_token = NULL;
  133. HANDLE primary_token = NULL;
  134. DWORD error = ERROR_SUCCESS;
  135. PWTS_SESSION_INFO session_info_ptr = NULL;
  136. DWORD count = 0;
  137. WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &session_info_ptr, &count);
  138. int size = sizeof(WTS_SESSION_INFO);
  139. DWORD active_session_id = (DWORD)-1;
  140. for(DWORD i=0; i<count; ++i) {
  141. WTS_SESSION_INFO item = session_info_ptr[i];
  142. OP_PRINTF("State: %d", item.State);
  143. if(WTSActive == item.State || WTSConnected == item.State) {
  144. LPTSTR pbuf = NULL;
  145. DWORD dwLen = 0;
  146. if(!WTSQuerySessionInformation(WTS_CURRENT_SERVER_NAME,
  147. item.SessionId, WTSUserName,
  148. &pbuf, &dwLen)) {
  149. error = GetLastError();
  150. OP_PRINTF("WTSUserName failed, GLE=%u", error);
  151. } else {
  152. OP_PRINTF("UserName: %s", pbuf);
  153. }
  154. if(lpcszUserName != NULL && strlen(lpcszUserName) > 0
  155. && strcmp(pbuf, lpcszUserName) == 0) {
  156. active_session_id = item.SessionId;
  157. OP_PRINTF("Retrieve specified session id: %d", active_session_id);
  158. break;
  159. }
  160. if(pbuf) {
  161. WTSFreeMemory(pbuf);
  162. pbuf = NULL;
  163. }
  164. }
  165. }
  166. WTSFreeMemory(session_info_ptr);
  167. if(active_session_id == DWORD(-1)) {
  168. error = ERROR_NO_SUCH_LOGON_SESSION;
  169. OP_PRINTF("Cannot find specified session id from username: %s", lpcszUserName);
  170. SetLastError(error);
  171. return false;
  172. }
  173. sessionID = active_session_id;
  174. BOOL ret = WTSQueryUserToken(active_session_id, &cur_token);
  175. if(!ret) {
  176. error = GetLastError();
  177. OP_PRINTF("Query active user token failed, GLE=%u.", error);
  178. SetLastError(error);
  179. token = INVALID_HANDLE_VALUE;
  180. return true;
  181. }
  182. ret = DuplicateTokenEx(cur_token, TOKEN_ASSIGN_PRIMARY|TOKEN_ALL_ACCESS, NULL,
  183. SecurityImpersonation, TokenPrimary, &primary_token);
  184. if(!ret) {
  185. error = GetLastError();
  186. OP_PRINTF("DuplicateTokenEx failed, GLE=%u.", error);
  187. SetLastError(error);
  188. primary_token = INVALID_HANDLE_VALUE;
  189. }
  190. CloseHandle(cur_token);
  191. token = primary_token;
  192. return true;
  193. }
  194. bool LaunchApplication(PSP_CREATE_PROCESS_INFO NewProcInfo)
  195. {
  196. LOG_FUNCTION();
  197. DWORD cur_session_id = WTSGetActiveConsoleSessionId();
  198. DWORD dmp_session_id = cur_session_id;
  199. if(cur_session_id == (DWORD)-1) {
  200. OP_PRINTF("There are no session attached to the physical console.");
  201. NewProcInfo->dwLastError = ERROR_CTX_SESSION_IN_USE;
  202. return false;
  203. }
  204. //Sleep(3000);
  205. OP_PRINTF("WTSGetActiveConsoleSessionId returned %d", cur_session_id);
  206. HANDLE token = INVALID_HANDLE_VALUE;
  207. if(!GetCurrentUserToken(token, cur_session_id, NewProcInfo->szUserName)) {
  208. NewProcInfo->dwLastError = GetLastError();
  209. OP_PRINTF("Get current user token failed (%d).", NewProcInfo->dwLastError);
  210. cur_session_id = dmp_session_id;
  211. return false;
  212. }
  213. //SetTokenInformation(token, TokenSessionId, &cur_session_id, sizeof(DWORD));
  214. //if(token != NULL && token != INVALID_HANDLE_VALUE) {
  215. // CloseHandle(token);
  216. //}
  217. //PROCESSENTRY32 proce_entry;
  218. //HANDLE h_snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  219. //if(h_snap == INVALID_HANDLE_VALUE) {
  220. // NewProcInfo->dwLastError = GetLastError();
  221. // OP_PRINTF("CreateToolhelp32Snapshot failed, GLE=%u", NewProcInfo->dwLastError);
  222. // return false;
  223. //}
  224. //proce_entry.dwSize = sizeof(PROCESSENTRY32);
  225. //if(!Process32First(h_snap, &proce_entry)) {
  226. // NewProcInfo->dwLastError = GetLastError();
  227. // OP_PRINTF("Process32First failed, GLE=%u", NewProcInfo->dwLastError);
  228. // CloseHandle(h_snap);
  229. // return false;
  230. //}
  231. //DWORD dw_winlogon_pid = -1;
  232. //Retrieves the Remote Desktop Services session associated with a specified process.
  233. //do
  234. //{
  235. // if(!_stricmp(proce_entry.szExeFile, "winlogon.exe")) {
  236. // DWORD winlogon_session_id = 0;
  237. // if(ProcessIdToSessionId(proce_entry.th32ProcessID, &winlogon_session_id)
  238. // && winlogon_session_id == cur_session_id) {
  239. // dw_winlogon_pid = proce_entry.th32ProcessID;
  240. // break;
  241. // }
  242. // }
  243. //} while (Process32Next(h_snap, &proce_entry));
  244. //CloseHandle(h_snap);
  245. //if(dw_winlogon_pid == -1) {
  246. // OP_PRINTF("Find the specified \"winlogon.exe\" failed.");
  247. // NewProcInfo->dwLastError = ERROR_NO_LOGON_SERVERS;
  248. // return false;
  249. //}
  250. DWORD dw_flag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
  251. PROCESS_INFORMATION pi;
  252. STARTUPINFO si;
  253. memset(&pi, 0, sizeof(PROCESS_INFORMATION));
  254. memset(&si, 0, sizeof(STARTUPINFO));
  255. si.cb = sizeof(STARTUPINFO);
  256. //Window station and desktop
  257. si.lpDesktop = "WinSta0\\Default";
  258. //HANDLE h_wl_token = NULL;
  259. //HANDLE h_wl_proc = OpenProcess(MAXIMUM_ALLOWED, FALSE, dw_winlogon_pid);
  260. //if(!::OpenProcessToken(h_wl_proc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
  261. // | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID
  262. // | TOKEN_READ | TOKEN_WRITE, &h_wl_token)) {
  263. // NewProcInfo->dwLastError = GetLastError();
  264. // OP_PRINTF("OpenProcessToken from winlogon failed, GLE=%u", NewProcInfo->dwLastError);
  265. // return false;
  266. //}
  267. //TOKEN_PRIVILEGES tp;
  268. //LUID luid;
  269. //if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
  270. // NewProcInfo->dwLastError = GetLastError();
  271. // OP_PRINTF("LookupPrivilegeValue from winlogon failed, GLE=%u", NewProcInfo->dwLastError);
  272. // CloseHandle(h_wl_token);
  273. // CloseHandle(h_wl_proc);
  274. // return false;
  275. //}
  276. //tp.PrivilegeCount = 1;
  277. //tp.Privileges[0].Luid = luid;
  278. //tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  279. //HANDLE h_user_token = INVALID_HANDLE_VALUE;
  280. //if(!WTSQueryUserToken(cur_session_id, &h_user_token)) {
  281. // OP_PRINTF("WTSQueryUserToken failed, GLE=%u.", GetLastError());
  282. //}
  283. //HANDLE h_user_token_duplicated = NULL;
  284. //DuplicateTokenEx(h_wl_token, MAXIMUM_ALLOWED, NULL,
  285. // SecurityIdentification, TokenPrimary, &h_user_token_duplicated);
  286. //if(!SetTokenInformation(h_user_token_duplicated, TokenSessionId,
  287. // (void*)&cur_session_id, sizeof(DWORD))) {
  288. // NewProcInfo->dwLastError = GetLastError();
  289. // OP_PRINTF("SetTokenInformation failed, GLE=%u", NewProcInfo->dwLastError);
  290. // CloseHandle(h_wl_proc);
  291. // CloseHandle(h_user_token_duplicated);
  292. // CloseHandle(h_wl_token);
  293. // return false;
  294. //}
  295. //if(!AdjustTokenPrivileges(h_user_token_duplicated, FALSE,
  296. // &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, NULL)) {
  297. // NewProcInfo->dwLastError = GetLastError();
  298. // OP_PRINTF("AdjustTokenPrivileges from winlogon failed, GLE=%u", NewProcInfo->dwLastError);
  299. // //CloseHandle(h_user_token);
  300. // CloseHandle(h_wl_proc);
  301. // CloseHandle(h_user_token_duplicated);
  302. // CloseHandle(h_wl_token);
  303. // return false;
  304. //}
  305. //if(GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
  306. // NewProcInfo->dwLastError = ERROR_NOT_ALL_ASSIGNED;
  307. // OP_PRINTF("Have not such privilege.");
  308. // //CloseHandle(h_user_token);
  309. // CloseHandle(h_wl_proc);
  310. // CloseHandle(h_user_token_duplicated);
  311. // CloseHandle(h_wl_token);
  312. // return false;
  313. //}
  314. LPVOID env = NULL;
  315. if(CreateEnvironmentBlock(&env, token, TRUE)) {
  316. dw_flag |= CREATE_UNICODE_ENVIRONMENT;
  317. }else {
  318. env = NULL;
  319. }
  320. char szExeLine[MAX_PATH*2] = {0};
  321. strcpy_s(szExeLine, NewProcInfo->szCmdline);
  322. OP_PRINTF("ExePath: (%s)[0X%X] 0X%X", szExeLine, token, env);
  323. BOOL res = CreateProcessAsUserA(token, NULL, szExeLine,
  324. NULL, NULL, FALSE, dw_flag, env, NULL, &si, &pi);
  325. if(!res) {
  326. NewProcInfo->dwLastError = GetLastError();
  327. OP_PRINTF("CreateProcessAsUser failed, GLE=%u", NewProcInfo->dwLastError);
  328. } else {
  329. OP_PRINTF("CreateProcessAsUser succ.");
  330. NewProcInfo->usValiSize = sizeof(PROCESS_INFORMATION);
  331. memcpy(&(NewProcInfo->pi), &pi, sizeof(PROCESS_INFORMATION));
  332. }
  333. if(!env) {
  334. DestroyEnvironmentBlock(env);
  335. }
  336. //RevertToSelf();
  337. //CloseHandle(h_wl_proc);
  338. //CloseHandle(h_user_token_duplicated);
  339. //CloseHandle(h_wl_token);
  340. CloseHandle(token);
  341. return !!res;
  342. }
  343. unsigned int WINAPI thread_procedure(void *param)
  344. {
  345. OP_PRINTF("thread_procdure routine enter.");
  346. while (WaitForSingleObject(g_srv_stop_event, 0) != WAIT_OBJECT_0) {
  347. Sleep(3000);
  348. }
  349. OP_PRINTF("thread_procdure routine exit.");
  350. return 0;
  351. }
  352. void WINAPI service_main(DWORD argc, LPTSTR *argv)
  353. {
  354. OP_PRINTF("service_main enter.");
  355. g_srv_status_handle = RegisterServiceCtrlHandler(SERVICE_SPECIFICED_NAME, service_ctrl_handle);
  356. if(!g_srv_status_handle) {
  357. OP_PRINTF("RegisterServiceCtrlHandler failed (%d).", GetLastError());
  358. goto pt_quit;
  359. }
  360. //not accept any controls while it is performing its initialization.
  361. memset(&g_srv_status, 0, sizeof(SERVICE_STATUS));
  362. if(!ChangeServiceStatus(SERVICE_START_PENDING, 0, 3000)) {
  363. OP_PRINTF("SetServiceStatus failed");
  364. goto pt_quit;
  365. }
  366. g_srv_stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
  367. if(!g_srv_stop_event) {
  368. OP_PRINTF("Create event failed");
  369. if(!ChangeServiceStatus(SERVICE_STOP, GetLastError(), 0)) {
  370. OP_PRINTF("SetServiceStatus as stop failed");
  371. }
  372. goto pt_quit;
  373. }
  374. HANDLE h_handle = (HANDLE)_beginthreadex(NULL, 0, thread_procedure, NULL, 0, NULL);
  375. if(h_handle == NULL || h_handle == INVALID_HANDLE_VALUE) {
  376. OP_PRINTF("Create thread of procedure failed (%d).", GetLastError());
  377. if(!ChangeServiceStatus(SERVICE_STOP, GetLastError(), 0)) {
  378. OP_PRINTF("SetServiceStatus as stop failed");
  379. }
  380. goto pt_quit;
  381. }
  382. //ready to accept controls.
  383. if(!ChangeServiceStatus(SERVICE_RUNNING, NO_ERROR, 0)) {
  384. OP_PRINTF("SetServiceStatus as running failed");
  385. goto pt_quit;
  386. }
  387. OP_PRINTF("Waiting for worker thread to complete.");
  388. WaitForSingleObject(h_handle, INFINITE);
  389. OP_PRINTF("Work thread event signaled !");
  390. if(!ChangeServiceStatus(SERVICE_STOPPED, NO_ERROR, 0)) {
  391. OP_PRINTF("SetServiceStatus as stopped failed");
  392. }
  393. pt_quit:
  394. OP_PRINTF("service_main exit.");
  395. return;
  396. }
  397. void WINAPI service_ctrl_handle(DWORD ctl_code)
  398. {
  399. OP_PRINTF("service_ctrl_handle routine enter.");
  400. switch(ctl_code)
  401. {
  402. case SERVICE_CONTROL_STOP:
  403. OP_PRINTF("SERVICE_CONTROL_STOP - command received.");
  404. if(g_srv_status.dwCurrentState != SERVICE_RUNNING) {
  405. break;
  406. }
  407. if(!ChangeServiceStatus(SERVICE_STOP_PENDING, 0, 0)) {
  408. OP_PRINTF("SetServiceStatus with stopp cmd failed");
  409. }
  410. SetEvent(g_srv_stop_event);
  411. break;
  412. case SERVICE_CONTROL_CREATEPROCESS:
  413. OP_PRINTF("SERVICE_CONTROL_CREATEPROCESS received.");
  414. {
  415. int szInfor = sizeof(SP_CREATE_PROCESS_INFO);
  416. HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szName);
  417. if (hMapFile == NULL) {
  418. OP_PRINTF("Could not open file mapping object, GLE=%u", GetLastError());
  419. break;
  420. }
  421. PSP_CREATE_PROCESS_INFO pBuf = (PSP_CREATE_PROCESS_INFO)
  422. MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, szInfor);
  423. if(pBuf == NULL) {
  424. OP_PRINTF("MapViewOfFile failed, GLE=%u.", GetLastError());
  425. CloseHandle(hMapFile);
  426. break;
  427. }
  428. OP_PRINTF("%s, %s", pBuf->szCmdline, pBuf->szUserName);
  429. LaunchApplication(pBuf);
  430. //UnmapViewOfFile(pBuf);
  431. CloseHandle(hMapFile);
  432. }
  433. break;
  434. default:
  435. break;
  436. }
  437. OP_PRINTF("service_ctrl_handle routine exit.");
  438. }
  439. //////////////////////////////////////////////////////////////////////////
  440. bool InstallService()
  441. {
  442. bool ret = true;
  443. char szPath[MAX_PATH];
  444. if( !GetModuleFileName(NULL, szPath, MAX_PATH ))
  445. {
  446. OP_PRINTF("GetModuleFileName failed (%d)", GetLastError());
  447. return false;
  448. }
  449. OP_PRINTF("Service path: %s", szPath);
  450. SC_HANDLE sch_mnr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  451. if(!sch_mnr) {
  452. OP_PRINTF("OpenSCManager failed (%d).", GetLastError());
  453. return false;
  454. }
  455. // Change start-type as auto-run [4/13/2018 14:22 @Gifur]
  456. SC_HANDLE sch_srv = CreateService(sch_mnr, SERVICE_SPECIFICED_NAME, "Rvc2wFreeWrap Service",
  457. SERVICE_ALL_ACCESS, SERVICE_WIN32_SHARE_PROCESS, SERVICE_AUTO_START/*SERVICE_DEMAND_START*/,
  458. SERVICE_ERROR_NORMAL,
  459. szPath, NULL, NULL, NULL, NULL, NULL);
  460. if(!sch_srv) {
  461. OP_PRINTF("CreateService failed (%d).", GetLastError());
  462. CloseServiceHandle(sch_mnr);
  463. return false;
  464. }
  465. CloseServiceHandle(sch_mnr);
  466. CloseServiceHandle(sch_srv);
  467. return true;
  468. }
  469. bool UnstallService()
  470. {
  471. bool ret = true;
  472. SC_HANDLE sch_mnr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  473. if(!sch_mnr) {
  474. OP_PRINTF("OpenSCManager failed (%d).", GetLastError());
  475. return false;
  476. }
  477. SC_HANDLE sch_srv = OpenService(sch_mnr, SERVICE_SPECIFICED_NAME, SERVICE_ALL_ACCESS);
  478. if(!sch_srv) {
  479. CloseServiceHandle(sch_mnr);
  480. OP_PRINTF("Open service failed (%d).", GetLastError());
  481. return false;
  482. }
  483. if(!DeleteService(sch_srv)) {
  484. CloseServiceHandle(sch_mnr);
  485. OP_PRINTF("Delete service failed (%d).", GetLastError());
  486. return false;
  487. }
  488. CloseServiceHandle(sch_srv);
  489. CloseServiceHandle(sch_mnr);
  490. OP_PRINTF("Delete service succ.");
  491. return true;
  492. }
  493. bool StopService()
  494. {
  495. bool ret = false;
  496. SERVICE_STATUS_PROCESS ssp;
  497. DWORD dwStartTime = GetTickCount();
  498. DWORD dwBytesNeeded;
  499. DWORD dwTimeout = 30000; // 30-second time-out
  500. DWORD dwWaitTime;
  501. SC_HANDLE sch_mnr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  502. if(!sch_mnr) {
  503. OP_PRINTF("OpenSCManager failed (%d).", GetLastError());
  504. return false;
  505. }
  506. SC_HANDLE sch_srv = OpenService(sch_mnr, SERVICE_SPECIFICED_NAME,
  507. SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS);
  508. if(!sch_srv) {
  509. CloseServiceHandle(sch_mnr);
  510. OP_PRINTF("Open service failed (%d).", GetLastError());
  511. return false;
  512. }
  513. // Make sure the service is not already stopped.
  514. if ( !QueryServiceStatusEx(
  515. sch_srv,
  516. SC_STATUS_PROCESS_INFO,
  517. (LPBYTE)&ssp,
  518. sizeof(SERVICE_STATUS_PROCESS),
  519. &dwBytesNeeded ) )
  520. {
  521. OP_PRINTF("QueryServiceStatusEx failed (%d)", GetLastError());
  522. goto stop_cleanup;
  523. }
  524. if ( ssp.dwCurrentState == SERVICE_STOPPED )
  525. {
  526. OP_PRINTF("Service is already stopped.");
  527. ret = true;
  528. goto stop_cleanup;
  529. }
  530. // If a stop is pending, wait for it.
  531. while ( ssp.dwCurrentState == SERVICE_STOP_PENDING )
  532. {
  533. OP_PRINTF("Service stop pending...");
  534. // Do not wait longer than the wait hint. A good interval is
  535. // one-tenth of the wait hint but not less than 1 second
  536. // and not more than 10 seconds.
  537. dwWaitTime = ssp.dwWaitHint / 10;
  538. if( dwWaitTime < 1000 )
  539. dwWaitTime = 1000;
  540. else if ( dwWaitTime > 10000 )
  541. dwWaitTime = 10000;
  542. Sleep( dwWaitTime );
  543. if ( !QueryServiceStatusEx(
  544. sch_srv,
  545. SC_STATUS_PROCESS_INFO,
  546. (LPBYTE)&ssp,
  547. sizeof(SERVICE_STATUS_PROCESS),
  548. &dwBytesNeeded ) )
  549. {
  550. OP_PRINTF("QueryServiceStatusEx failed (%d)", GetLastError());
  551. goto stop_cleanup;
  552. }
  553. if ( ssp.dwCurrentState == SERVICE_STOPPED )
  554. {
  555. OP_PRINTF("Service stopped succ.");
  556. ret = true;
  557. goto stop_cleanup;
  558. }
  559. if ( GetTickCount() - dwStartTime > dwTimeout )
  560. {
  561. OP_PRINTF("Service stop timed out.");
  562. goto stop_cleanup;
  563. }
  564. }
  565. // If the service is running, dependencies must be stopped first.
  566. StopDependentServices(sch_mnr, sch_srv);
  567. // Send a stop code to the service.
  568. if ( !ControlService(
  569. sch_srv,
  570. SERVICE_CONTROL_STOP,
  571. (LPSERVICE_STATUS) &ssp ) )
  572. {
  573. OP_PRINTF( "ControlService failed (%d)", GetLastError() );
  574. goto stop_cleanup;
  575. }
  576. // Wait for the service to stop.
  577. while ( ssp.dwCurrentState != SERVICE_STOPPED )
  578. {
  579. Sleep( ssp.dwWaitHint );
  580. if ( !QueryServiceStatusEx(
  581. sch_srv,
  582. SC_STATUS_PROCESS_INFO,
  583. (LPBYTE)&ssp,
  584. sizeof(SERVICE_STATUS_PROCESS),
  585. &dwBytesNeeded ) )
  586. {
  587. OP_PRINTF( "QueryServiceStatusEx failed (%d)", GetLastError() );
  588. goto stop_cleanup;
  589. }
  590. if ( ssp.dwCurrentState == SERVICE_STOPPED ) {
  591. ret = true;
  592. break;
  593. }
  594. if ( GetTickCount() - dwStartTime > dwTimeout )
  595. {
  596. OP_PRINTF( "Wait timed out" );
  597. goto stop_cleanup;
  598. }
  599. }
  600. stop_cleanup:
  601. CloseServiceHandle(sch_srv);
  602. CloseServiceHandle(sch_mnr);
  603. if(ret) {
  604. OP_PRINTF("Service stopped succ.");
  605. }
  606. return ret;
  607. }
  608. bool StartExService()
  609. {
  610. bool ret = false;
  611. SERVICE_STATUS_PROCESS ssStatus;
  612. DWORD dwOldCheckPoint;
  613. DWORD dwStartTickCount;
  614. DWORD dwWaitTime;
  615. DWORD dwBytesNeeded;
  616. SC_HANDLE sch_mnr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  617. if(!sch_mnr) {
  618. OP_PRINTF("OpenSCManager failed (%d).", GetLastError());
  619. return false;
  620. }
  621. SC_HANDLE sch_srv = OpenService(sch_mnr, SERVICE_SPECIFICED_NAME, SERVICE_ALL_ACCESS);
  622. if(!sch_srv) {
  623. CloseServiceHandle(sch_mnr);
  624. OP_PRINTF("Open service failed (%d).", GetLastError());
  625. return false;
  626. }
  627. // Check the status in case the service is not stopped.
  628. if (!QueryServiceStatusEx(
  629. sch_srv, // handle to service
  630. SC_STATUS_PROCESS_INFO, // information level
  631. (LPBYTE) &ssStatus, // address of structure
  632. sizeof(SERVICE_STATUS_PROCESS), // size of structure
  633. &dwBytesNeeded ) ) // size needed if buffer is too small
  634. {
  635. OP_PRINTF("QueryServiceStatusEx failed (%d)", GetLastError());
  636. CloseServiceHandle(sch_srv);
  637. CloseServiceHandle(sch_mnr);
  638. return false;
  639. }
  640. // Check if the service is already running. It would be possible
  641. // to stop the service here, but for simplicity this example just returns.
  642. if(ssStatus.dwCurrentState != SERVICE_STOPPED && ssStatus.dwCurrentState != SERVICE_STOP_PENDING)
  643. {
  644. OP_PRINTF("Cannot start the service because it is already running");
  645. CloseServiceHandle(sch_srv);
  646. CloseServiceHandle(sch_mnr);
  647. return true;
  648. }
  649. // Save the tick count and initial checkpoint.
  650. dwStartTickCount = GetTickCount();
  651. dwOldCheckPoint = ssStatus.dwCheckPoint;
  652. // Wait for the service to stop before attempting to start it.
  653. while (ssStatus.dwCurrentState == SERVICE_STOP_PENDING)
  654. {
  655. // Do not wait longer than the wait hint. A good interval is
  656. // one-tenth of the wait hint but not less than 1 second
  657. // and not more than 10 seconds.
  658. dwWaitTime = ssStatus.dwWaitHint / 10;
  659. if( dwWaitTime < 1000 )
  660. dwWaitTime = 1000;
  661. else if ( dwWaitTime > 10000 )
  662. dwWaitTime = 10000;
  663. Sleep( dwWaitTime );
  664. // Check the status until the service is no longer stop pending.
  665. if (!QueryServiceStatusEx(
  666. sch_srv, // handle to service
  667. SC_STATUS_PROCESS_INFO, // information level
  668. (LPBYTE) &ssStatus, // address of structure
  669. sizeof(SERVICE_STATUS_PROCESS), // size of structure
  670. &dwBytesNeeded ) ) // size needed if buffer is too small
  671. {
  672. OP_PRINTF("QueryServiceStatusEx failed (%d)", GetLastError());
  673. CloseServiceHandle(sch_srv);
  674. CloseServiceHandle(sch_mnr);
  675. return false;
  676. }
  677. if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
  678. {
  679. // Continue to wait and check.
  680. dwStartTickCount = GetTickCount();
  681. dwOldCheckPoint = ssStatus.dwCheckPoint;
  682. }
  683. else
  684. {
  685. if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
  686. {
  687. OP_PRINTF("Timeout waiting for service to stop");
  688. CloseServiceHandle(sch_srv);
  689. CloseServiceHandle(sch_mnr);
  690. return false;
  691. }
  692. }
  693. }
  694. // Attempt to start the service.
  695. if (!StartService(
  696. sch_srv, // handle to service
  697. 0, // number of arguments
  698. NULL) ) // no arguments
  699. {
  700. OP_PRINTF("StartService failed (%d)", GetLastError());
  701. CloseServiceHandle(sch_srv);
  702. CloseServiceHandle(sch_mnr);
  703. return false;
  704. }
  705. else {
  706. OP_PRINTF("Service start pending...");
  707. }
  708. // Check the status until the service is no longer start pending.
  709. if (!QueryServiceStatusEx(
  710. sch_srv, // handle to service
  711. SC_STATUS_PROCESS_INFO, // info level
  712. (LPBYTE) &ssStatus, // address of structure
  713. sizeof(SERVICE_STATUS_PROCESS), // size of structure
  714. &dwBytesNeeded ) ) // if buffer too small
  715. {
  716. OP_PRINTF("QueryServiceStatusEx failed (%d)", GetLastError());
  717. CloseServiceHandle(sch_srv);
  718. CloseServiceHandle(sch_mnr);
  719. return false;
  720. }
  721. // Save the tick count and initial checkpoint.
  722. dwStartTickCount = GetTickCount();
  723. dwOldCheckPoint = ssStatus.dwCheckPoint;
  724. while (ssStatus.dwCurrentState == SERVICE_START_PENDING)
  725. {
  726. // Do not wait longer than the wait hint. A good interval is
  727. // one-tenth the wait hint, but no less than 1 second and no
  728. // more than 10 seconds.
  729. dwWaitTime = ssStatus.dwWaitHint / 10;
  730. if( dwWaitTime < 1000 )
  731. dwWaitTime = 1000;
  732. else if ( dwWaitTime > 10000 )
  733. dwWaitTime = 10000;
  734. Sleep( dwWaitTime );
  735. // Check the status again.
  736. if (!QueryServiceStatusEx(
  737. sch_srv, // handle to service
  738. SC_STATUS_PROCESS_INFO, // info level
  739. (LPBYTE) &ssStatus, // address of structure
  740. sizeof(SERVICE_STATUS_PROCESS), // size of structure
  741. &dwBytesNeeded ) ) // if buffer too small
  742. {
  743. OP_PRINTF("QueryServiceStatusEx failed (%d)", GetLastError());
  744. break;
  745. }
  746. if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
  747. {
  748. // Continue to wait and check.
  749. dwStartTickCount = GetTickCount();
  750. dwOldCheckPoint = ssStatus.dwCheckPoint;
  751. }
  752. else
  753. {
  754. if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
  755. {
  756. // No progress made within the wait hint.
  757. break;
  758. }
  759. }
  760. }
  761. // Determine whether the service is running.
  762. if (ssStatus.dwCurrentState == SERVICE_RUNNING)
  763. {
  764. OP_PRINTF("Service started succ.");
  765. ret = true;
  766. }
  767. else
  768. {
  769. OP_PRINTF("Service not started.");
  770. OP_PRINTF(" Current State: %d", ssStatus.dwCurrentState);
  771. OP_PRINTF(" Exit Code: %d", ssStatus.dwWin32ExitCode);
  772. OP_PRINTF(" Check Point: %d", ssStatus.dwCheckPoint);
  773. OP_PRINTF(" Wait Hint: %d", ssStatus.dwWaitHint);
  774. }
  775. CloseServiceHandle(sch_srv);
  776. CloseServiceHandle(sch_mnr);
  777. return ret;
  778. }
  779. // Updates the service DACL to grant start, stop, delete, and read control access to the ClientUser account.
  780. bool __stdcall UpdateServiceDacl()
  781. {
  782. bool ret = false;
  783. EXPLICIT_ACCESS ea;
  784. SECURITY_DESCRIPTOR sd;
  785. PSECURITY_DESCRIPTOR psd = NULL;
  786. PACL pacl = NULL;
  787. PACL pNewAcl = NULL;
  788. BOOL bDaclPresent = FALSE;
  789. BOOL bDaclDefaulted = FALSE;
  790. DWORD dwError = 0;
  791. DWORD dwSize = 0;
  792. DWORD dwBytesNeeded = 0;
  793. SC_HANDLE sch_mnr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  794. if(!sch_mnr) {
  795. OP_PRINTF("OpenSCManager failed (%d).", GetLastError());
  796. return false;
  797. }
  798. SC_HANDLE sch_srv = OpenService(sch_mnr, SERVICE_SPECIFICED_NAME,
  799. READ_CONTROL | WRITE_DAC);
  800. if(!sch_srv) {
  801. CloseServiceHandle(sch_mnr);
  802. OP_PRINTF("Open service failed (%d).", GetLastError());
  803. return false;
  804. }
  805. // Get the current security descriptor.
  806. if (!QueryServiceObjectSecurity(sch_srv,
  807. DACL_SECURITY_INFORMATION,
  808. &psd, // using NULL does not work on all versions
  809. 0,
  810. &dwBytesNeeded))
  811. {
  812. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  813. {
  814. dwSize = dwBytesNeeded;
  815. psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),
  816. HEAP_ZERO_MEMORY, dwSize);
  817. if (psd == NULL)
  818. {
  819. // Note: HeapAlloc does not support GetLastError.
  820. OP_PRINTF("HeapAlloc failed");
  821. goto dacl_cleanup;
  822. }
  823. if (!QueryServiceObjectSecurity(sch_srv,
  824. DACL_SECURITY_INFORMATION, psd, dwSize, &dwBytesNeeded))
  825. {
  826. OP_PRINTF("QueryServiceObjectSecurity failed (%d)", GetLastError());
  827. goto dacl_cleanup;
  828. }
  829. }
  830. else
  831. {
  832. OP_PRINTF("QueryServiceObjectSecurity failed (%d)", GetLastError());
  833. goto dacl_cleanup;
  834. }
  835. }
  836. // Get the DACL.
  837. if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl,
  838. &bDaclDefaulted))
  839. {
  840. OP_PRINTF("GetSecurityDescriptorDacl failed(%d)", GetLastError());
  841. goto dacl_cleanup;
  842. }
  843. // Build the ACE.
  844. BuildExplicitAccessWithName(&ea, TEXT(ANOTHER_USERNAME),
  845. SERVICE_START | SERVICE_STOP | READ_CONTROL | DELETE,
  846. SET_ACCESS, NO_INHERITANCE);
  847. dwError = SetEntriesInAcl(1, &ea, pacl, &pNewAcl);
  848. if (dwError != ERROR_SUCCESS)
  849. {
  850. OP_PRINTF("SetEntriesInAcl failed(%d)", dwError);
  851. goto dacl_cleanup;
  852. }
  853. // Initialize a new security descriptor.
  854. if (!InitializeSecurityDescriptor(&sd,
  855. SECURITY_DESCRIPTOR_REVISION))
  856. {
  857. OP_PRINTF("InitializeSecurityDescriptor failed(%d)", GetLastError());
  858. goto dacl_cleanup;
  859. }
  860. // Set the new DACL in the security descriptor.
  861. if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE))
  862. {
  863. OP_PRINTF("SetSecurityDescriptorDacl failed(%d)", GetLastError());
  864. goto dacl_cleanup;
  865. }
  866. // Set the new DACL for the service object.
  867. if (!SetServiceObjectSecurity(sch_srv,
  868. DACL_SECURITY_INFORMATION, &sd))
  869. {
  870. OP_PRINTF("SetServiceObjectSecurity failed(%d)", GetLastError());
  871. goto dacl_cleanup;
  872. }
  873. else {
  874. OP_PRINTF("Service DACL updated succ.");
  875. ret = true;
  876. }
  877. dacl_cleanup:
  878. CloseServiceHandle(sch_srv);
  879. CloseServiceHandle(sch_mnr);
  880. if(NULL != pNewAcl)
  881. LocalFree((HLOCAL)pNewAcl);
  882. if(NULL != psd)
  883. HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
  884. return ret;
  885. }
  886. int _tmain(int argc, char* argv[])
  887. {
  888. int ret = 0;
  889. InitLogConfig();
  890. OP_PRINTF("main routine enter.");
  891. if(argc > 1) {
  892. if(strcmp(argv[1], "-i") == 0) {
  893. if(InstallService()) {
  894. OP_PRINTF("Install service cmd succ.");
  895. } else {
  896. ret = 1;
  897. OP_PRINTF("Error occurs when installing service.");
  898. }
  899. } else if(strcmp(argv[1], "-u") == 0) {
  900. if(!StopService()) {
  901. ret = 1;
  902. OP_PRINTF("Error occurs when stoping service.");
  903. }else {
  904. if(UnstallService()) {
  905. OP_PRINTF("Unstall service cmd succ.");
  906. } else {
  907. ret = 1;
  908. OP_PRINTF("Error occurs when unstalling service.");
  909. }
  910. }
  911. } else if(strcmp(argv[1], "-s") == 0) {
  912. if(StopService()) {
  913. OP_PRINTF("Stop service cmd succ.");
  914. } else {
  915. ret = 1;
  916. OP_PRINTF("Error occurs when stoping service.");
  917. }
  918. } else if(strcmp(argv[1], "-t") == 0) {
  919. if(StartExService()) {
  920. OP_PRINTF("Start service cmd succ.");
  921. UpdateServiceDacl();
  922. } else {
  923. ret = 1;
  924. OP_PRINTF("Error occurs when starting service.");
  925. }
  926. } else if(strcmp(argv[1], "-d") == 0) {
  927. if(UpdateServiceDacl()) {
  928. OP_PRINTF("Dacl service cmd succ.");
  929. } else {
  930. ret = 1;
  931. OP_PRINTF("Error occurs when dacling service.");
  932. }
  933. }else {
  934. OP_PRINTF("illegal paramters.");
  935. ret = 2;
  936. }
  937. }
  938. else {
  939. SERVICE_TABLE_ENTRY srv_table[] = {
  940. {SERVICE_SPECIFICED_NAME, (LPSERVICE_MAIN_FUNCTION)service_main},
  941. {NULL, NULL}
  942. };
  943. if(!StartServiceCtrlDispatcher(srv_table)) {
  944. DWORD dwError = GetLastError();
  945. OP_PRINTF("StartServiceCtrlDispatcher failed. GLE=%u", dwError);
  946. if(dwError == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
  947. OP_PRINTF("ERROR_FAILED_SERVICE_CONTROLLER_CONNECT");
  948. else if (dwError == ERROR_INVALID_DATA)
  949. OP_PRINTF("ERROR_INVALID_DATA");
  950. else if (dwError == ERROR_SERVICE_ALREADY_RUNNING)
  951. OP_PRINTF("ERROR_SERVICE_ALREADY_RUNNING");
  952. return 3;
  953. }
  954. }
  955. OP_PRINTF("main routine exit.");
  956. return ret;
  957. }