Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2591 lines
63 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ts2.c
  5. Abstract:
  6. This is a test program for exercising the service controller. This
  7. program acts like a service and exercises the Service Controller API
  8. that can be called from a service:
  9. NetServiceStartCtrlDispatcher
  10. NetServiceRegisterCtrlHandler
  11. NetServiceStatus
  12. Contents:
  13. Grumpy
  14. Lumpy
  15. Dumpy
  16. Sleepy
  17. Dead
  18. SlowStop - Takes a long time to stop based on Message Box.
  19. Terminate - Starts normally, After 20 seconds, it sends a STOPPED
  20. status, and does an ExitProcess.
  21. Bad1 - Never calls RegisterServiceCtrlHandler.
  22. Bad2 - Stays in START_PENDING forever.
  23. Bad3 - Start= Sends 1 START_PENDING, then doesn't send any further
  24. status messages. Otherwise operates normally.
  25. Bad4 - Normal Start; On Stop it sends 1 stop pending status then
  26. terminates itself.
  27. HangOnStop - Doesn't return from CtrlHandl routine on Stop
  28. requests until 40 seconds has passed. (pipe timeout is 30 sec).
  29. Sends a RUNNING status after the 40 second wait, then it sleeps
  30. for 20 seconds before sending STOPPED status.
  31. StartAndDie - Takes 40 seconds to start, then it terminates
  32. right after saying it was started.
  33. Author:
  34. Dan Lafferty (danl) 12 Apr-1991
  35. Environment:
  36. User Mode -Win32
  37. Notes:
  38. optional-notes
  39. Revision History:
  40. --*/
  41. //
  42. // Includes
  43. //
  44. #include <nt.h> // DbgPrint prototype
  45. #include <ntrtl.h> // DbgPrint prototype
  46. #include <windef.h>
  47. #include <nturtl.h> // needed for winbase.h
  48. #include <winbase.h>
  49. #include <wingdi.h> // for winuserp.h
  50. #include <winuser.h> // MessageBox
  51. #include <winuserp.h> // STARTF_DESKTOPINHERIT
  52. #include <wincon.h> // CONSOLE_SCREEN_BUFFER_INFO
  53. #include <winsvc.h>
  54. #include <tstr.h> // Unicode string macros
  55. #include <stdio.h> // printf
  56. //
  57. // Defines
  58. //
  59. #define INFINITE_WAIT_TIME 0xffffffff
  60. #define NULL_STRING TEXT("");
  61. LPWSTR pszInteractiveDesktop=L"WinSta0\\Default";
  62. //
  63. // Globals
  64. //
  65. HANDLE DbgLogFileHandle = INVALID_HANDLE_VALUE;
  66. SERVICE_STATUS GrumpyStatus;
  67. SERVICE_STATUS LumpyStatus;
  68. SERVICE_STATUS DumpyStatus;
  69. SERVICE_STATUS SleepyStatus;
  70. SERVICE_STATUS DeadStatus;
  71. SERVICE_STATUS SlowStopStatus;
  72. SERVICE_STATUS TerminateStatus;
  73. SERVICE_STATUS Bad1Status;
  74. SERVICE_STATUS Bad2Status;
  75. SERVICE_STATUS Bad3Status;
  76. SERVICE_STATUS Bad4Status;
  77. SERVICE_STATUS HangOnStopStatus;
  78. SERVICE_STATUS StartProcStatus;
  79. SERVICE_STATUS StartAndDieStatus;
  80. HANDLE GrumpyDoneEvent;
  81. HANDLE LumpyDoneEvent;
  82. HANDLE DumpyDoneEvent;
  83. HANDLE SleepyDoneEvent;
  84. HANDLE DeadDoneEvent;
  85. HANDLE SlowStopDoneEvent;
  86. HANDLE TerminateDoneEvent;
  87. HANDLE Bad1DoneEvent;
  88. HANDLE Bad2DoneEvent;
  89. HANDLE Bad3DoneEvent;
  90. HANDLE Bad4DoneEvent;
  91. HANDLE HangOnStopDoneEvent;
  92. HANDLE StartProcDoneEvent;
  93. HANDLE StartAndDieDoneEvent;
  94. SERVICE_STATUS_HANDLE GrumpyStatusHandle;
  95. SERVICE_STATUS_HANDLE LumpyStatusHandle;
  96. SERVICE_STATUS_HANDLE DumpyStatusHandle;
  97. SERVICE_STATUS_HANDLE SleepyStatusHandle;
  98. SERVICE_STATUS_HANDLE DeadStatusHandle;
  99. SERVICE_STATUS_HANDLE SlowStopStatusHandle;
  100. SERVICE_STATUS_HANDLE TerminateStatusHandle;
  101. SERVICE_STATUS_HANDLE Bad1StatusHandle;
  102. SERVICE_STATUS_HANDLE Bad2StatusHandle;
  103. SERVICE_STATUS_HANDLE Bad3StatusHandle;
  104. SERVICE_STATUS_HANDLE Bad4StatusHandle;
  105. SERVICE_STATUS_HANDLE HangOnStopStatusHandle;
  106. SERVICE_STATUS_HANDLE StartProcStatusHandle;
  107. SERVICE_STATUS_HANDLE StartAndDieStatusHandle;
  108. //
  109. // Function Prototypes
  110. //
  111. DWORD
  112. GrumpyStart (
  113. DWORD argc,
  114. LPTSTR *argv
  115. );
  116. DWORD
  117. LumpyStart (
  118. DWORD argc,
  119. LPTSTR *argv
  120. );
  121. DWORD
  122. DumpyStart (
  123. DWORD argc,
  124. LPTSTR *argv
  125. );
  126. DWORD
  127. SleepyStart (
  128. DWORD argc,
  129. LPTSTR *argv
  130. );
  131. DWORD
  132. DeadStart (
  133. DWORD argc,
  134. LPTSTR *argv
  135. );
  136. DWORD
  137. SlowStopStart (
  138. DWORD argc,
  139. LPTSTR *argv
  140. );
  141. DWORD
  142. TerminateStart (
  143. DWORD argc,
  144. LPTSTR *argv
  145. );
  146. DWORD
  147. Bad1Start (DWORD argc,LPTSTR *argv);
  148. DWORD
  149. Bad2Start (DWORD argc,LPTSTR *argv);
  150. DWORD
  151. Bad3Start (DWORD argc,LPTSTR *argv);
  152. DWORD
  153. Bad4Start (DWORD argc,LPTSTR *argv);
  154. DWORD
  155. HangOnStopStart (DWORD argc,LPTSTR *argv);
  156. DWORD
  157. StartProcStart (DWORD argc,LPTSTR *argv);
  158. DWORD
  159. StartAndDieStart (DWORD argc,LPTSTR *argv);
  160. VOID
  161. GrumpyCtrlHandler (
  162. IN DWORD opcode
  163. );
  164. VOID
  165. LumpyCtrlHandler (
  166. IN DWORD opcode
  167. );
  168. VOID
  169. DumpyCtrlHandler (
  170. IN DWORD opcode
  171. );
  172. VOID
  173. SleepyCtrlHandler (
  174. IN DWORD opcode
  175. );
  176. VOID
  177. DeadCtrlHandler (
  178. IN DWORD opcode
  179. );
  180. VOID
  181. SlowStopCtrlHandler (
  182. IN DWORD opcode
  183. );
  184. VOID
  185. TerminateCtrlHandler (
  186. IN DWORD opcode
  187. );
  188. VOID
  189. Bad1CtrlHandler (IN DWORD opcode);
  190. VOID
  191. Bad2CtrlHandler (IN DWORD opcode);
  192. VOID
  193. Bad3CtrlHandler (IN DWORD opcode);
  194. VOID
  195. Bad4CtrlHandler (IN DWORD opcode);
  196. VOID
  197. HangOnStopCtrlHandler (IN DWORD opcode);
  198. VOID
  199. StartProcCtrlHandler (IN DWORD opcode);
  200. VOID
  201. StartAndDieCtrlHandler (IN DWORD opcode);
  202. VOID
  203. SvcPrintf (char *Format, ...);
  204. VOID
  205. SetUpConsole();
  206. /****************************************************************************/
  207. VOID __cdecl
  208. main (
  209. DWORD argc,
  210. PCHAR argv[]
  211. )
  212. {
  213. DWORD i;
  214. SERVICE_TABLE_ENTRY DispatchTable[] = {
  215. { TEXT("StartProc"), StartProcStart },
  216. { TEXT("grumpy"), GrumpyStart },
  217. { TEXT("lumpy"), LumpyStart },
  218. { TEXT("dumpy"), DumpyStart },
  219. { TEXT("sleepy"), SleepyStart },
  220. { TEXT("dead"), DeadStart },
  221. { TEXT("slowstop"), SlowStopStart },
  222. { TEXT("terminate"), TerminateStart },
  223. { TEXT("Bad1"), Bad1Start },
  224. { TEXT("Bad2"), Bad2Start },
  225. { TEXT("Bad3"), Bad3Start },
  226. { TEXT("Bad4"), Bad4Start },
  227. { TEXT("HangOnStop"), HangOnStopStart },
  228. { TEXT("StartAndDie"), StartAndDieStart },
  229. { NULL, NULL }
  230. };
  231. DbgPrint("[ts2]Args passed to .exe main() function:\n");
  232. for (i=0; i<argc; i++) {
  233. DbgPrint(" [TS2] CommandArg%d = %s\n", i,argv[i]);
  234. }
  235. //SetUpConsole();
  236. if (!StartServiceCtrlDispatcher( DispatchTable)) {
  237. DbgPrint("[ts2]StartServiceCtrlDispatcher returned error %d\n",GetLastError);
  238. }
  239. DbgPrint("[ts2]The Service Process is Terminating....\n");
  240. ExitProcess(0);
  241. }
  242. /****************************************************************************/
  243. //
  244. // Grumpy will take a long time to respond to pause
  245. //
  246. //
  247. DWORD
  248. GrumpyStart (
  249. DWORD argc,
  250. LPTSTR *argv
  251. )
  252. {
  253. DWORD status;
  254. DWORD i;
  255. //---------------------------------------------------------------------
  256. SC_HANDLE SCHandle;
  257. SC_HANDLE ServiceHandle;
  258. //---------------------------------------------------------------------
  259. DbgPrint(" [GRUMPY] Inside the Grumpy Service Thread\n");
  260. for (i=0; i<argc; i++) {
  261. DbgPrint(" [GRUMPY] CommandArg%d = %s\n", i,argv[i]);
  262. }
  263. GrumpyDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  264. //
  265. // Fill in this services status structure
  266. //
  267. GrumpyStatus.dwServiceType = SERVICE_WIN32;
  268. GrumpyStatus.dwCurrentState = SERVICE_RUNNING;
  269. GrumpyStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  270. SERVICE_ACCEPT_PAUSE_CONTINUE;
  271. //
  272. // Set up bogus values for status.
  273. //
  274. GrumpyStatus.dwWin32ExitCode = 14;
  275. GrumpyStatus.dwServiceSpecificExitCode = 55;
  276. GrumpyStatus.dwCheckPoint = 53;
  277. GrumpyStatus.dwWaitHint = 22;
  278. //
  279. // Register the Control Handler routine.
  280. //
  281. DbgPrint(" [GRUMPY] Getting Ready to call RegisterServiceCtrlHandler\n");
  282. GrumpyStatusHandle = RegisterServiceCtrlHandler(
  283. TEXT("grumpy"),
  284. GrumpyCtrlHandler);
  285. if (GrumpyStatusHandle == (SERVICE_STATUS_HANDLE)0) {
  286. DbgPrint(" [GRUMPY] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  287. }
  288. //
  289. // Return the status
  290. //
  291. if (!SetServiceStatus (GrumpyStatusHandle, &GrumpyStatus)) {
  292. status = GetLastError();
  293. DbgPrint(" [GRUMPY] SetServiceStatus error %ld\n",status);
  294. }
  295. #define START_SERVICE
  296. #ifdef START_SERVICE
  297. //---------------------------------------------------------------------
  298. //
  299. // TEMP CODE - Start another service
  300. //
  301. DbgPrint("[GRUMPY] Attempt to start Messinger");
  302. if ((SCHandle = OpenSCManager(NULL,NULL,SC_MANAGER_CONNECT))!= NULL) {
  303. if ((ServiceHandle = OpenService(
  304. SCHandle,
  305. TEXT("Messinger"),
  306. SERVICE_START)) != NULL) {
  307. if (!StartService(ServiceHandle,0,NULL)) {
  308. DbgPrint("[GRUMPY] StartService Failed, rc = %d",
  309. GetLastError());
  310. }
  311. }
  312. else {
  313. DbgPrint("GRUMPY] OpenService failed %d\n",GetLastError());
  314. }
  315. }
  316. else {
  317. DbgPrint("GRUMPY] OpenSCManager failed %d\n",GetLastError());
  318. }
  319. //
  320. //
  321. //
  322. //---------------------------------------------------------------------
  323. #endif
  324. //
  325. // Wait forever until we are told to terminate.
  326. //
  327. status = WaitForSingleObject (
  328. GrumpyDoneEvent,
  329. INFINITE_WAIT_TIME);
  330. DbgPrint(" [GRUMPY] Leaving the grumpy service\n");
  331. CloseHandle(GrumpyDoneEvent);
  332. return(NO_ERROR);
  333. }
  334. /****************************************************************************/
  335. VOID
  336. GrumpyCtrlHandler (
  337. IN DWORD Opcode
  338. )
  339. {
  340. DWORD status;
  341. DbgPrint(" [GRUMPY] opcode = %ld\n", Opcode);
  342. //
  343. // Find and operate on the request.
  344. //
  345. switch(Opcode) {
  346. case SERVICE_CONTROL_PAUSE:
  347. Sleep(60000); // 1 minute
  348. GrumpyStatus.dwCurrentState = SERVICE_PAUSED;
  349. break;
  350. case SERVICE_CONTROL_CONTINUE:
  351. GrumpyStatus.dwCurrentState = SERVICE_RUNNING;
  352. break;
  353. case SERVICE_CONTROL_STOP:
  354. GrumpyStatus.dwWin32ExitCode = 0;
  355. GrumpyStatus.dwServiceSpecificExitCode = 0;
  356. GrumpyStatus.dwCurrentState = SERVICE_STOPPED;
  357. GrumpyStatus.dwWaitHint = 0;
  358. GrumpyStatus.dwCheckPoint = 0;
  359. SetEvent(GrumpyDoneEvent);
  360. break;
  361. case SERVICE_CONTROL_INTERROGATE:
  362. //
  363. // Send a BAD Status Response
  364. //
  365. DbgPrint(" [GRUMPY] Sending bogus status (0x00000000)\n");
  366. if (!SetServiceStatus (0L, &GrumpyStatus)) {
  367. status = GetLastError();
  368. DbgPrint(" [GRUMPY] SetServiceStatus error %ld "
  369. " - - Expect %d\n",status,ERROR_INVALID_HANDLE);
  370. }
  371. DbgPrint(" [GRUMPY] Sending bogus status (0xefefefef)\n");
  372. if (!SetServiceStatus (0xefefefef, &GrumpyStatus)) {
  373. status = GetLastError();
  374. DbgPrint(" [GRUMPY] SetServiceStatus error %ld "
  375. " - - Expect %d\n",status,ERROR_INVALID_HANDLE);
  376. }
  377. break;
  378. default:
  379. DbgPrint(" [GRUMPY] Unrecognized opcode %ld\n", Opcode);
  380. }
  381. //
  382. // Send a status response.
  383. //
  384. if (!SetServiceStatus (GrumpyStatusHandle, &GrumpyStatus)) {
  385. status = GetLastError();
  386. DbgPrint(" [GRUMPY] SetServiceStatus error %ld\n",status);
  387. }
  388. return;
  389. }
  390. /****************************************************************************/
  391. DWORD
  392. LumpyStart (
  393. DWORD argc,
  394. LPTSTR *argv
  395. )
  396. {
  397. DWORD status;
  398. DWORD i;
  399. DbgPrint(" [LUMPY] Inside the Lumpy Service Thread\n");
  400. for (i=0; i<argc; i++) {
  401. DbgPrint(" [LUMPY] CommandArg%d = %s\n", i,argv[i]);
  402. }
  403. LumpyDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  404. //
  405. // Fill in this services status structure
  406. //
  407. LumpyStatus.dwServiceType = SERVICE_WIN32|SERVICE_INTERACTIVE_PROCESS;
  408. LumpyStatus.dwCurrentState = SERVICE_RUNNING;
  409. LumpyStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  410. SERVICE_ACCEPT_PAUSE_CONTINUE |
  411. SERVICE_ACCEPT_SHUTDOWN;
  412. LumpyStatus.dwWin32ExitCode = 0;
  413. LumpyStatus.dwServiceSpecificExitCode = 0;
  414. LumpyStatus.dwCheckPoint = 0;
  415. LumpyStatus.dwWaitHint = 0;
  416. //
  417. // Register the Control Handler routine.
  418. //
  419. DbgPrint(" [LUMPY] Getting Ready to call RegisterServiceCtrlHandler\n");
  420. LumpyStatusHandle = RegisterServiceCtrlHandler(
  421. TEXT("lumpy"),
  422. LumpyCtrlHandler);
  423. if (LumpyStatusHandle == (SERVICE_STATUS_HANDLE)0) {
  424. DbgPrint(" [LUMPY] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  425. }
  426. //
  427. // Return the status
  428. //
  429. if (!SetServiceStatus (LumpyStatusHandle, &LumpyStatus)) {
  430. status = GetLastError();
  431. DbgPrint(" [LUMPY] SetServiceStatus error %ld\n",status);
  432. }
  433. //
  434. // Wait forever until we are told to terminate.
  435. //
  436. status = WaitForSingleObject (
  437. LumpyDoneEvent,
  438. INFINITE_WAIT_TIME);
  439. if (status == WAIT_FAILED) {
  440. DbgPrint(" [LUMPY] WaitLastError = %d\n",GetLastError());
  441. }
  442. DbgPrint(" [LUMPY] Leaving the lumpy service\n");
  443. CloseHandle(LumpyDoneEvent);
  444. return(NO_ERROR);
  445. }
  446. /****************************************************************************/
  447. VOID
  448. LumpyCtrlHandler (
  449. IN DWORD Opcode
  450. )
  451. {
  452. DWORD status;
  453. DbgPrint(" [LUMPY] opcode = %ld\n", Opcode);
  454. //
  455. // Find and operate on the request.
  456. //
  457. switch(Opcode) {
  458. case SERVICE_CONTROL_PAUSE:
  459. SvcPrintf("Lumpy received a PAUSE\n");
  460. LumpyStatus.dwCurrentState = SERVICE_PAUSED;
  461. break;
  462. case SERVICE_CONTROL_CONTINUE:
  463. SvcPrintf("Lumpy received a CONTINUE\n");
  464. LumpyStatus.dwCurrentState = SERVICE_RUNNING;
  465. break;
  466. case SERVICE_CONTROL_SHUTDOWN:
  467. case SERVICE_CONTROL_STOP:
  468. SvcPrintf("Lumpy received a STOP\n");
  469. LumpyStatus.dwWin32ExitCode = 0;
  470. LumpyStatus.dwCurrentState = SERVICE_STOPPED;
  471. if (!SetEvent(LumpyDoneEvent)) {
  472. DbgPrint(" [LUMPY] SetEvent Failed %d\n",GetLastError());
  473. }
  474. break;
  475. case SERVICE_CONTROL_INTERROGATE:
  476. SvcPrintf("Lumpy received an INTERROGATE\n");
  477. break;
  478. default:
  479. DbgPrint(" [LUMPY] Unrecognized opcode %ld\n", Opcode);
  480. }
  481. //
  482. // Send a status response.
  483. //
  484. if (!SetServiceStatus (LumpyStatusHandle, &LumpyStatus)) {
  485. status = GetLastError();
  486. DbgPrint(" [LUMPY] SetServiceStatus error %ld\n",status);
  487. }
  488. return;
  489. }
  490. /****************************************************************************/
  491. DWORD
  492. DumpyStart (
  493. DWORD argc,
  494. LPTSTR *argv
  495. )
  496. {
  497. DWORD status;
  498. DWORD i;
  499. DbgPrint(" [DUMPY] Inside the Dumpy Service Thread\n");
  500. for (i=0; i<argc; i++) {
  501. DbgPrint(" [DUMPY] CommandArg%d = %s\n", i,argv[i]);
  502. }
  503. DumpyDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  504. //
  505. // Fill in this services status structure
  506. //
  507. DumpyStatus.dwServiceType = SERVICE_WIN32;
  508. DumpyStatus.dwCurrentState = SERVICE_RUNNING;
  509. DumpyStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  510. SERVICE_ACCEPT_PAUSE_CONTINUE;
  511. DumpyStatus.dwWin32ExitCode = 0;
  512. DumpyStatus.dwServiceSpecificExitCode = 0;
  513. DumpyStatus.dwCheckPoint = 0;
  514. DumpyStatus.dwWaitHint = 0;
  515. //
  516. // Register the Control Handler routine.
  517. //
  518. DbgPrint(" [DUMPY] Getting Ready to call RegisterServiceCtrlHandler\n");
  519. DumpyStatusHandle = RegisterServiceCtrlHandler(
  520. TEXT("dumpy"),
  521. DumpyCtrlHandler);
  522. if (DumpyStatusHandle == (SERVICE_STATUS_HANDLE)0) {
  523. DbgPrint(" [DUMPY] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  524. }
  525. //
  526. // Return the status
  527. //
  528. if (!SetServiceStatus (DumpyStatusHandle, &DumpyStatus)) {
  529. status = GetLastError();
  530. DbgPrint(" [DUMPY] SetServiceStatus error %ld\n",status);
  531. }
  532. //
  533. // Wait forever until we are told to terminate.
  534. //
  535. status = WaitForSingleObject (
  536. DumpyDoneEvent,
  537. INFINITE_WAIT_TIME);
  538. DbgPrint(" [DUMPY] Leaving the dumpy service\n");
  539. CloseHandle(DumpyDoneEvent);
  540. return(NO_ERROR);
  541. }
  542. /****************************************************************************/
  543. VOID
  544. DumpyCtrlHandler (
  545. IN DWORD Opcode
  546. )
  547. {
  548. DWORD status;
  549. DbgPrint(" [DUMPY] opcode = %ld\n", Opcode);
  550. //
  551. // Find and operate on the request.
  552. //
  553. switch(Opcode) {
  554. case SERVICE_CONTROL_PAUSE:
  555. DumpyStatus.dwCurrentState = SERVICE_PAUSED;
  556. break;
  557. case SERVICE_CONTROL_CONTINUE:
  558. DumpyStatus.dwCurrentState = SERVICE_RUNNING;
  559. break;
  560. case SERVICE_CONTROL_STOP:
  561. DumpyStatus.dwWin32ExitCode = 0;
  562. DumpyStatus.dwCurrentState = SERVICE_STOPPED;
  563. SetEvent(DumpyDoneEvent);
  564. break;
  565. case SERVICE_CONTROL_INTERROGATE:
  566. break;
  567. default:
  568. DbgPrint(" [DUMPY] Unrecognized opcode %ld\n", Opcode);
  569. }
  570. //
  571. // Send a status response.
  572. //
  573. if (!SetServiceStatus (DumpyStatusHandle, &DumpyStatus)) {
  574. status = GetLastError();
  575. DbgPrint(" [DUMPY] SetServiceStatus error %ld\n",status);
  576. }
  577. return;
  578. }
  579. /****************************************************************************/
  580. DWORD
  581. SleepyStart (
  582. DWORD argc,
  583. LPTSTR *argv
  584. )
  585. {
  586. DWORD status;
  587. DWORD i;
  588. DWORD checkpoint=1;
  589. DbgPrint(" [SLEEPY] Inside the Sleepy Service Thread\n");
  590. for (i=0; i<argc; i++) {
  591. DbgPrint(" [SLEEPY] CommandArg%d = %s\n", i,argv[i]);
  592. }
  593. SleepyDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  594. //
  595. // Fill in this services status structure
  596. //
  597. SleepyStatus.dwServiceType = SERVICE_WIN32;
  598. SleepyStatus.dwCurrentState = SERVICE_START_PENDING;
  599. SleepyStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  600. SERVICE_ACCEPT_PAUSE_CONTINUE;
  601. SleepyStatus.dwWin32ExitCode = 0;
  602. SleepyStatus.dwServiceSpecificExitCode = 0;
  603. SleepyStatus.dwCheckPoint = checkpoint++;
  604. SleepyStatus.dwWaitHint = 40000;
  605. //
  606. // Register the Control Handler routine.
  607. //
  608. DbgPrint(" [SLEEPY] Getting Ready to call RegisterServiceCtrlHandler\n");
  609. SleepyStatusHandle = RegisterServiceCtrlHandler(
  610. TEXT("sleepy"),
  611. SleepyCtrlHandler);
  612. if (SleepyStatusHandle == (SERVICE_STATUS_HANDLE)0) {
  613. DbgPrint(" [SLEEPY] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  614. }
  615. //
  616. // This service tests the install pending system in the service
  617. // controller. Therefore, it loops and sleeps 4 times prior to
  618. // indicating that installation is complete.
  619. //
  620. for (i=0; i<5; i++) {
  621. //
  622. // Return the status
  623. //
  624. DbgPrint(" [SLEEPY] sending install status #%d\n",i);
  625. if (!SetServiceStatus (SleepyStatusHandle, &SleepyStatus)) {
  626. status = GetLastError();
  627. DbgPrint(" [SLEEPY] SetServiceStatus error %ld\n",status);
  628. }
  629. Sleep(20000); // Sleep for 20 seconds
  630. status = WaitForSingleObject (
  631. SleepyDoneEvent,
  632. 0);
  633. if (status == 0) {
  634. DbgPrint(" [SLEEPY] terminated while installing\n");
  635. return(NO_ERROR);
  636. }
  637. //
  638. // Increment the checkpoint value in status. (20 seconds)
  639. //
  640. SleepyStatus.dwCheckPoint = checkpoint++;
  641. SleepyStatus.dwWaitHint = 40000;
  642. DbgPrint(" [SLEEPY] checkpoint = 0x%lx\n",SleepyStatus.dwCheckPoint);
  643. #ifdef SpecialTest
  644. //
  645. //******************************************************************
  646. // TEST out the condition where we have an unsolicited uninstall
  647. // after sending the first status message.
  648. //
  649. SleepyStatus.dwWin32ExitCode = 0;
  650. SleepyStatus.dwCurrentState = SERVICE_STOPPED;
  651. if (!SetServiceStatus (SleepyStatusHandle, &SleepyStatus)) {
  652. status = GetLastError();
  653. DbgPrint("[SLEEPY] Error From SetServiceStatus %d\n",status);
  654. }
  655. DbgPrint(" [SLEEPY] Leaving the Sleepy service\n");
  656. return(NO_ERROR);
  657. //
  658. //******************************************************************
  659. #endif //SpecialTest
  660. }
  661. DbgPrint(" [SLEEPY] setting up installed status\n");
  662. SleepyStatus.dwCurrentState = SERVICE_RUNNING;
  663. SleepyStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  664. SERVICE_ACCEPT_PAUSE_CONTINUE;
  665. SleepyStatus.dwWin32ExitCode = 0;
  666. SleepyStatus.dwServiceSpecificExitCode = 0;
  667. SleepyStatus.dwCheckPoint = 0;
  668. SleepyStatus.dwWaitHint = 0;
  669. DbgPrint(" [SLEEPY] sending install status #%d\n",i);
  670. if (!SetServiceStatus (SleepyStatusHandle, &SleepyStatus)) {
  671. status = GetLastError();
  672. DbgPrint(" [SLEEPY] SetServiceStatus error %ld\n",status);
  673. }
  674. //
  675. // Wait forever until we are told to terminate.
  676. //
  677. status = WaitForSingleObject (
  678. SleepyDoneEvent,
  679. INFINITE_WAIT_TIME);
  680. DbgPrint(" [SLEEPY] Leaving the Sleepy service\n");
  681. CloseHandle(SleepyDoneEvent);
  682. return(NO_ERROR);
  683. }
  684. /****************************************************************************/
  685. VOID
  686. SleepyCtrlHandler (
  687. IN DWORD Opcode
  688. )
  689. {
  690. DWORD status;
  691. DbgPrint(" [SLEEPY] opcode = %ld\n", Opcode);
  692. //
  693. // Find and operate on the request.
  694. //
  695. switch(Opcode) {
  696. case SERVICE_CONTROL_PAUSE:
  697. SleepyStatus.dwCurrentState = SERVICE_PAUSED;
  698. break;
  699. case SERVICE_CONTROL_CONTINUE:
  700. SleepyStatus.dwCurrentState = SERVICE_RUNNING;
  701. break;
  702. case SERVICE_CONTROL_STOP:
  703. SleepyStatus.dwWin32ExitCode = 0;
  704. SleepyStatus.dwCheckPoint = 0;
  705. SleepyStatus.dwWaitHint = 0;
  706. SleepyStatus.dwCurrentState = SERVICE_STOPPED;
  707. SetEvent(SleepyDoneEvent);
  708. break;
  709. case SERVICE_CONTROL_INTERROGATE:
  710. break;
  711. default:
  712. DbgPrint(" [SLEEPY] Unrecognized opcode %ld\n", Opcode);
  713. }
  714. //
  715. // Send a status response.
  716. //
  717. if (!SetServiceStatus (SleepyStatusHandle, &SleepyStatus)) {
  718. status = GetLastError();
  719. DbgPrint(" [SLEEPY] SetServiceStatus error %ld\n",status);
  720. }
  721. return;
  722. }
  723. /****************************************************************************/
  724. DWORD
  725. DeadStart (
  726. DWORD argc,
  727. LPTSTR *argv
  728. )
  729. {
  730. DWORD status;
  731. DWORD i;
  732. DbgPrint(" [DEAD] Inside the Dead Service Thread\n");
  733. for (i=0; i<argc; i++) {
  734. DbgPrint(" [DEAD] CommandArg%d = %s\n", i,argv[i]);
  735. }
  736. DeadDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  737. //
  738. // Fill in this services status structure
  739. //
  740. DeadStatus.dwServiceType = SERVICE_WIN32;
  741. DeadStatus.dwCurrentState = SERVICE_STOPPED;
  742. DeadStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  743. SERVICE_ACCEPT_PAUSE_CONTINUE;
  744. DeadStatus.dwWin32ExitCode = 0x00020002;
  745. DeadStatus.dwServiceSpecificExitCode = 0;
  746. DeadStatus.dwCheckPoint = 0;
  747. DeadStatus.dwWaitHint = 0;
  748. //
  749. // Register the Control Handler routine.
  750. //
  751. DbgPrint(" [DEAD] Getting Ready to call RegisterServiceCtrlHandler\n");
  752. DeadStatusHandle = RegisterServiceCtrlHandler(
  753. TEXT("dead"),
  754. DeadCtrlHandler);
  755. if (DeadStatusHandle == (SERVICE_STATUS_HANDLE)0) {
  756. DbgPrint(" [DEAD] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  757. }
  758. //
  759. // The Dead Service will now exit process prior to sending its first
  760. // status.
  761. //
  762. DbgPrint(" [DEAD] Terminating the Dead Service Process\n");
  763. ExitProcess(0);
  764. //
  765. // Return the status
  766. //
  767. if (!SetServiceStatus (DeadStatusHandle, &DeadStatus)) {
  768. status = GetLastError();
  769. DbgPrint(" [DEAD] SetServiceStatus error %ld\n",status);
  770. }
  771. //
  772. // Wait forever until we are told to terminate.
  773. //
  774. status = WaitForSingleObject (
  775. DeadDoneEvent,
  776. INFINITE_WAIT_TIME);
  777. DbgPrint(" [DEAD] Leaving the dead service\n");
  778. CloseHandle(DeadDoneEvent);
  779. return(NO_ERROR);
  780. }
  781. /****************************************************************************/
  782. VOID
  783. DeadCtrlHandler (
  784. IN DWORD Opcode
  785. )
  786. {
  787. DWORD status;
  788. DbgPrint(" [DEAD] opcode = %ld\n", Opcode);
  789. //
  790. // Find and operate on the request.
  791. //
  792. switch(Opcode) {
  793. case SERVICE_CONTROL_PAUSE:
  794. DeadStatus.dwCurrentState = SERVICE_PAUSED;
  795. break;
  796. case SERVICE_CONTROL_CONTINUE:
  797. DeadStatus.dwCurrentState = SERVICE_RUNNING;
  798. break;
  799. case SERVICE_CONTROL_STOP:
  800. DeadStatus.dwWin32ExitCode = 0;
  801. DeadStatus.dwCurrentState = SERVICE_STOPPED;
  802. SetEvent(DeadDoneEvent);
  803. break;
  804. case SERVICE_CONTROL_INTERROGATE:
  805. break;
  806. default:
  807. DbgPrint(" [DEAD] Unrecognized opcode %ld\n", Opcode);
  808. }
  809. //
  810. // Send a status response.
  811. //
  812. if (!SetServiceStatus (DeadStatusHandle, &DeadStatus)) {
  813. status = GetLastError();
  814. DbgPrint(" [DEAD] SetServiceStatus error %ld\n",status);
  815. }
  816. return;
  817. }
  818. /****************************************************************************/
  819. //
  820. // SlowStop will take a long time to stop.
  821. //
  822. //
  823. DWORD
  824. SlowStopStart (
  825. DWORD argc,
  826. LPTSTR *argv
  827. )
  828. {
  829. DWORD status;
  830. DWORD i;
  831. DWORD LoopCount;
  832. DbgPrint(" [SLOW_STOP] Inside the SlowStop Service Thread\n");
  833. for (i=0; i<argc; i++) {
  834. DbgPrint(" [SLOW_STOP] CommandArg%d = %s\n", i,argv[i]);
  835. }
  836. SlowStopDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  837. //
  838. // Fill in this services status structure
  839. //
  840. SlowStopStatus.dwServiceType = SERVICE_WIN32;
  841. SlowStopStatus.dwCurrentState = SERVICE_RUNNING;
  842. SlowStopStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  843. SERVICE_ACCEPT_PAUSE_CONTINUE |
  844. SERVICE_ACCEPT_SHUTDOWN;
  845. SlowStopStatus.dwWin32ExitCode = 0;
  846. SlowStopStatus.dwServiceSpecificExitCode = 0;
  847. SlowStopStatus.dwCheckPoint = 0;
  848. SlowStopStatus.dwWaitHint = 0;
  849. //
  850. // Register the Control Handler routine.
  851. //
  852. DbgPrint(" [SLOW_STOP] Getting Ready to call RegisterServiceCtrlHandler\n");
  853. SlowStopStatusHandle = RegisterServiceCtrlHandler(
  854. TEXT("slowstop"),
  855. SlowStopCtrlHandler);
  856. if (SlowStopStatusHandle == (SERVICE_STATUS_HANDLE)0) {
  857. DbgPrint(" [SLOW_STOP] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  858. }
  859. //
  860. // Return the status
  861. //
  862. if (!SetServiceStatus (SlowStopStatusHandle, &SlowStopStatus)) {
  863. status = GetLastError();
  864. DbgPrint(" [SLOW_STOP] SetServiceStatus error %ld\n",status);
  865. }
  866. //
  867. // Put up a message box to get information on how long it should take
  868. // this service to stop. The choices are to stop within the WaitHint
  869. // time period - and to stop outside of the WaitHint time period
  870. //
  871. //
  872. // Ask the user how long to take in stopping
  873. //
  874. status = MessageBox(
  875. NULL,
  876. "Press YES Stop occurs within WaitHint Period\n"
  877. "Press NO Stop takes longer than the WaitHint Period\n"
  878. "Press CANCEL Stop occurs within WaitHint Period",
  879. "SlowStopStart",
  880. MB_YESNOCANCEL | MB_SERVICE_NOTIFICATION);
  881. DbgPrint("MessageBox return status = %d\n",status);
  882. SvcPrintf("I got the status\n");
  883. switch(status){
  884. case IDNO:
  885. LoopCount = 30;
  886. break;
  887. case IDYES:
  888. LoopCount = 6;
  889. break;
  890. case IDCANCEL:
  891. LoopCount = 6;
  892. break;
  893. }
  894. //
  895. // Wait forever until we are told to terminate.
  896. //
  897. status = WaitForSingleObject (
  898. SlowStopDoneEvent,
  899. INFINITE_WAIT_TIME);
  900. //===============================================
  901. //
  902. // When shutting down, send the STOP_PENDING
  903. // status for 8 seconds then STOP.
  904. // The WaitHint indicates it takes 10 seconds
  905. // to stop.
  906. //
  907. //===============================================
  908. for (i=0; i<LoopCount ; i++ ) {
  909. Sleep(1000);
  910. SlowStopStatus.dwCheckPoint++;
  911. if (!SetServiceStatus (SlowStopStatusHandle, &SlowStopStatus)) {
  912. status = GetLastError();
  913. DbgPrint(" [SLOW_STOP] SetServiceStatus error %ld\n",status);
  914. }
  915. }
  916. SlowStopStatus.dwCurrentState = SERVICE_STOPPED;
  917. SlowStopStatus.dwCheckPoint=0;
  918. SlowStopStatus.dwWaitHint=0;
  919. if (!SetServiceStatus (SlowStopStatusHandle, &SlowStopStatus)) {
  920. status = GetLastError();
  921. DbgPrint(" [SLOW_STOP] SetServiceStatus error %ld\n",status);
  922. }
  923. DbgPrint(" [SLOW_STOP] Leaving the slowstop service\n");
  924. CloseHandle(SlowStopDoneEvent);
  925. return(NO_ERROR);
  926. }
  927. /****************************************************************************/
  928. VOID
  929. SlowStopCtrlHandler (
  930. IN DWORD Opcode
  931. )
  932. {
  933. DWORD status;
  934. DbgPrint(" [SLOW_STOP] opcode = %ld\n", Opcode);
  935. //
  936. // Find and operate on the request.
  937. //
  938. switch(Opcode) {
  939. case SERVICE_CONTROL_PAUSE:
  940. SlowStopStatus.dwCurrentState = SERVICE_PAUSED;
  941. break;
  942. case SERVICE_CONTROL_CONTINUE:
  943. SlowStopStatus.dwCurrentState = SERVICE_RUNNING;
  944. break;
  945. case SERVICE_CONTROL_STOP:
  946. case SERVICE_CONTROL_SHUTDOWN:
  947. SlowStopStatus.dwWin32ExitCode = 0;
  948. SlowStopStatus.dwServiceSpecificExitCode = 0;
  949. SlowStopStatus.dwCurrentState = SERVICE_STOP_PENDING;
  950. SlowStopStatus.dwWaitHint = 10000; // 10 seconds to stop
  951. // SlowStopStatus.dwWaitHint = 0; // 10 seconds to stop
  952. SlowStopStatus.dwCheckPoint = 1;
  953. SetEvent(SlowStopDoneEvent);
  954. break;
  955. case SERVICE_CONTROL_INTERROGATE:
  956. break;
  957. default:
  958. DbgPrint(" [SLOW_STOP] Unrecognized opcode %ld\n", Opcode);
  959. }
  960. //
  961. // Send a status response.
  962. //
  963. if (!SetServiceStatus (SlowStopStatusHandle, &SlowStopStatus)) {
  964. status = GetLastError();
  965. DbgPrint(" [SLOW_STOP] SetServiceStatus error %ld\n",status);
  966. }
  967. return;
  968. }
  969. /****************************************************************************/
  970. //
  971. // Terminate will die unexpectedly.
  972. //
  973. //
  974. DWORD
  975. TerminateStart (
  976. DWORD argc,
  977. LPTSTR *argv
  978. )
  979. {
  980. DWORD status;
  981. DWORD i;
  982. DbgPrint(" [TERMINATE] Inside the Terminate Service Thread\n");
  983. for (i=0; i<argc; i++) {
  984. DbgPrint(" [TERMINATE] CommandArg%d = %s\n", i,argv[i]);
  985. }
  986. TerminateDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  987. //
  988. // Fill in this services status structure
  989. //
  990. TerminateStatus.dwServiceType = SERVICE_WIN32;
  991. TerminateStatus.dwCurrentState = SERVICE_RUNNING;
  992. TerminateStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  993. SERVICE_ACCEPT_PAUSE_CONTINUE;
  994. TerminateStatus.dwWin32ExitCode = 0;
  995. TerminateStatus.dwServiceSpecificExitCode = 0;
  996. TerminateStatus.dwCheckPoint = 0;
  997. TerminateStatus.dwWaitHint = 0;
  998. //
  999. // Register the Control Handler routine.
  1000. //
  1001. DbgPrint(" [TERMINATE] Getting Ready to call RegisterServiceCtrlHandler\n");
  1002. TerminateStatusHandle = RegisterServiceCtrlHandler(
  1003. TEXT("terminate"),
  1004. TerminateCtrlHandler);
  1005. if (TerminateStatusHandle == (SERVICE_STATUS_HANDLE)0) {
  1006. DbgPrint(" [TERMINATE] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  1007. }
  1008. //
  1009. // Return the status
  1010. //
  1011. if (!SetServiceStatus (TerminateStatusHandle, &TerminateStatus)) {
  1012. status = GetLastError();
  1013. DbgPrint(" [TERMINATE] SetServiceStatus error %ld\n",status);
  1014. }
  1015. //=======================================================================
  1016. //
  1017. // Sleep for 20 seconds, then send out an error status, and ExitProcess.
  1018. // NOTE: It would be more proper for a service to ExitThread here
  1019. // instead. But who says test services need to be proper?
  1020. //
  1021. //=======================================================================
  1022. Sleep(20000);
  1023. TerminateStatus.dwCurrentState = SERVICE_STOPPED;
  1024. TerminateStatus.dwWin32ExitCode = ERROR_INVALID_ENVIRONMENT;
  1025. TerminateStatus.dwCheckPoint=0;
  1026. TerminateStatus.dwWaitHint=0;
  1027. if (!SetServiceStatus (TerminateStatusHandle, &TerminateStatus)) {
  1028. status = GetLastError();
  1029. DbgPrint(" [TERMINATE] SetServiceStatus error %ld\n",status);
  1030. }
  1031. ExitProcess(NO_ERROR);
  1032. return(NO_ERROR);
  1033. }
  1034. /****************************************************************************/
  1035. VOID
  1036. TerminateCtrlHandler (
  1037. IN DWORD Opcode
  1038. )
  1039. {
  1040. DWORD status;
  1041. DbgPrint(" [TERMINATE] opcode = %ld\n", Opcode);
  1042. //
  1043. // Find and operate on the request.
  1044. //
  1045. switch(Opcode) {
  1046. case SERVICE_CONTROL_PAUSE:
  1047. TerminateStatus.dwCurrentState = SERVICE_PAUSED;
  1048. break;
  1049. case SERVICE_CONTROL_CONTINUE:
  1050. TerminateStatus.dwCurrentState = SERVICE_RUNNING;
  1051. break;
  1052. case SERVICE_CONTROL_STOP:
  1053. TerminateStatus.dwWin32ExitCode = 0;
  1054. TerminateStatus.dwServiceSpecificExitCode = 0;
  1055. TerminateStatus.dwCurrentState = SERVICE_STOP_PENDING;
  1056. TerminateStatus.dwCheckPoint = 1;
  1057. TerminateStatus.dwWaitHint = 20000;
  1058. SetEvent(TerminateDoneEvent);
  1059. break;
  1060. case SERVICE_CONTROL_INTERROGATE:
  1061. break;
  1062. default:
  1063. DbgPrint(" [TERMINATE] Unrecognized opcode %ld\n", Opcode);
  1064. }
  1065. //
  1066. // Send a status response.
  1067. //
  1068. if (!SetServiceStatus (TerminateStatusHandle, &TerminateStatus)) {
  1069. status = GetLastError();
  1070. DbgPrint(" [TERMINATE] SetServiceStatus error %ld\n",status);
  1071. }
  1072. CloseHandle(TerminateDoneEvent);
  1073. return;
  1074. }
  1075. /****************************************************************************/
  1076. //
  1077. // Bad1 will never call RegisterServiceCtrlHandler.
  1078. //
  1079. //
  1080. DWORD
  1081. Bad1Start (
  1082. DWORD argc,
  1083. LPTSTR *argv
  1084. )
  1085. {
  1086. DWORD status;
  1087. DWORD i;
  1088. DbgPrint(" [BAD1] Inside the Bad1 Service Thread\n");
  1089. for (i=0; i<argc; i++) {
  1090. DbgPrint(" [BAD1] CommandArg%d = %s\n", i,argv[i]);
  1091. }
  1092. Bad1DoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  1093. //
  1094. // Fill in this services status structure
  1095. //
  1096. Bad1Status.dwServiceType = SERVICE_WIN32;
  1097. Bad1Status.dwCurrentState = SERVICE_START_PENDING;
  1098. Bad1Status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  1099. SERVICE_ACCEPT_PAUSE_CONTINUE;
  1100. Bad1Status.dwWin32ExitCode = 0;
  1101. Bad1Status.dwServiceSpecificExitCode = 0;
  1102. Bad1Status.dwCheckPoint = 1;
  1103. Bad1Status.dwWaitHint = 5000;
  1104. //
  1105. // Register the Control Handler routine.
  1106. //
  1107. /////////////////////////////////
  1108. // Sleep for a real long time
  1109. // without calling RegisterServiceCtrlHandler.
  1110. DbgPrint(" [BAD1] Getting Ready to sleep\n");
  1111. Sleep(9999999);
  1112. ////////////////////////////////////////////////
  1113. //
  1114. //
  1115. // Wait forever until we are told to terminate.
  1116. //
  1117. status = WaitForSingleObject (
  1118. Bad1DoneEvent,
  1119. INFINITE_WAIT_TIME);
  1120. DbgPrint(" [BAD1] Leaving the Bad1 service\n");
  1121. CloseHandle(Bad1DoneEvent);
  1122. return(NO_ERROR);
  1123. }
  1124. /****************************************************************************/
  1125. VOID
  1126. Bad1CtrlHandler (
  1127. IN DWORD Opcode
  1128. )
  1129. {
  1130. DWORD status;
  1131. DbgPrint(" [BAD1] opcode = %ld\n", Opcode);
  1132. //
  1133. // Find and operate on the request.
  1134. //
  1135. switch(Opcode) {
  1136. case SERVICE_CONTROL_PAUSE:
  1137. Bad1Status.dwCurrentState = SERVICE_PAUSED;
  1138. break;
  1139. case SERVICE_CONTROL_CONTINUE:
  1140. Bad1Status.dwCurrentState = SERVICE_RUNNING;
  1141. break;
  1142. case SERVICE_CONTROL_STOP:
  1143. Bad1Status.dwWin32ExitCode = 0;
  1144. Bad1Status.dwServiceSpecificExitCode = 0;
  1145. Bad1Status.dwCurrentState = SERVICE_STOP_PENDING;
  1146. Bad1Status.dwCheckPoint = 1;
  1147. Bad1Status.dwWaitHint = 20000;
  1148. SetEvent(Bad1DoneEvent);
  1149. break;
  1150. case SERVICE_CONTROL_INTERROGATE:
  1151. break;
  1152. default:
  1153. DbgPrint(" [BAD1] Unrecognized opcode %ld\n", Opcode);
  1154. }
  1155. //
  1156. // Send a status response.
  1157. //
  1158. if (!SetServiceStatus (Bad1StatusHandle, &Bad1Status)) {
  1159. status = GetLastError();
  1160. DbgPrint(" [BAD1] SetServiceStatus error %ld\n",status);
  1161. }
  1162. CloseHandle(Bad1DoneEvent);
  1163. return;
  1164. }
  1165. /****************************************************************************/
  1166. //
  1167. // Bad2 will never complete initialization (stuck in START_PENDING forever).
  1168. // The control handler is functioning and STOP is functioning.
  1169. //
  1170. //
  1171. DWORD
  1172. Bad2Start (
  1173. DWORD argc,
  1174. LPTSTR *argv
  1175. )
  1176. {
  1177. DWORD status;
  1178. DWORD i;
  1179. DbgPrint(" [BAD2] Inside the Bad2 Service Thread\n");
  1180. for (i=0; i<argc; i++) {
  1181. DbgPrint(" [BAD2] CommandArg%d = %s\n", i,argv[i]);
  1182. }
  1183. Bad2DoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  1184. //
  1185. // Fill in this services status structure
  1186. //
  1187. Bad2Status.dwServiceType = SERVICE_WIN32;
  1188. Bad2Status.dwCurrentState = SERVICE_START_PENDING;
  1189. Bad2Status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  1190. SERVICE_ACCEPT_PAUSE_CONTINUE;
  1191. Bad2Status.dwWin32ExitCode = 0;
  1192. Bad2Status.dwServiceSpecificExitCode = 0;
  1193. Bad2Status.dwCheckPoint = 1;
  1194. Bad2Status.dwWaitHint = 5000;
  1195. //
  1196. // Register the Control Handler routine.
  1197. //
  1198. DbgPrint(" [BAD2] Getting Ready to call RegisterServiceCtrlHandler\n");
  1199. Bad2StatusHandle = RegisterServiceCtrlHandler(
  1200. TEXT("Bad2"),
  1201. Bad2CtrlHandler);
  1202. if (Bad2StatusHandle == (SERVICE_STATUS_HANDLE)0) {
  1203. DbgPrint(" [BAD2] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  1204. }
  1205. //
  1206. // Return the status
  1207. //
  1208. if (!SetServiceStatus (Bad2StatusHandle, &Bad2Status)) {
  1209. status = GetLastError();
  1210. DbgPrint(" [BAD2] SetServiceStatus error %ld\n",status);
  1211. }
  1212. #ifdef remove
  1213. /////////////////////////////////
  1214. // Sleep for a real long time
  1215. // without sending status.
  1216. DbgPrint(" [BAD2] Getting Ready to sleep\n");
  1217. Sleep(9999999);
  1218. #endif
  1219. /////////////////////////////////
  1220. //
  1221. // Wait forever until we are told to terminate.
  1222. //
  1223. status = WaitForSingleObject (
  1224. Bad2DoneEvent,
  1225. INFINITE_WAIT_TIME);
  1226. DbgPrint(" [BAD2] Leaving the Bad2 service\n");
  1227. CloseHandle(Bad2DoneEvent);
  1228. return(NO_ERROR);
  1229. }
  1230. /****************************************************************************/
  1231. VOID
  1232. Bad2CtrlHandler (
  1233. IN DWORD Opcode
  1234. )
  1235. {
  1236. DWORD status;
  1237. DbgPrint(" [BAD2] opcode = %ld\n", Opcode);
  1238. //
  1239. // Find and operate on the request.
  1240. //
  1241. switch(Opcode) {
  1242. case SERVICE_CONTROL_PAUSE:
  1243. Bad2Status.dwCurrentState = SERVICE_PAUSED;
  1244. break;
  1245. case SERVICE_CONTROL_CONTINUE:
  1246. Bad2Status.dwCurrentState = SERVICE_RUNNING;
  1247. break;
  1248. case SERVICE_CONTROL_STOP:
  1249. Bad2Status.dwWin32ExitCode = 0;
  1250. Bad2Status.dwServiceSpecificExitCode = 0;
  1251. Bad2Status.dwCurrentState = SERVICE_STOPPED;
  1252. Bad2Status.dwCheckPoint = 1;
  1253. Bad2Status.dwWaitHint = 5000;
  1254. SetEvent(Bad2DoneEvent);
  1255. break;
  1256. case SERVICE_CONTROL_INTERROGATE:
  1257. break;
  1258. default:
  1259. DbgPrint(" [BAD2] Unrecognized opcode %ld\n", Opcode);
  1260. }
  1261. //
  1262. // Send a status response.
  1263. //
  1264. if (!SetServiceStatus (Bad2StatusHandle, &Bad2Status)) {
  1265. status = GetLastError();
  1266. DbgPrint(" [BAD2] SetServiceStatus error %ld\n",status);
  1267. }
  1268. CloseHandle(Bad2DoneEvent);
  1269. return;
  1270. }
  1271. /****************************************************************************/
  1272. //
  1273. // Bad3 will send only its first START_PENDING status, and then it won't send
  1274. // any further status messages for any reason. Aside from not sending any
  1275. // status messages, the service operates normally.
  1276. //
  1277. DWORD
  1278. Bad3Start (
  1279. DWORD argc,
  1280. LPTSTR *argv
  1281. )
  1282. {
  1283. DWORD status;
  1284. DWORD i;
  1285. DbgPrint(" [BAD3] Inside the Bad3 Service Thread\n");
  1286. for (i=0; i<argc; i++) {
  1287. DbgPrint(" [BAD3] CommandArg%d = %s\n", i,argv[i]);
  1288. }
  1289. Bad3DoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  1290. //
  1291. // Fill in this services status structure
  1292. //
  1293. Bad3Status.dwServiceType = SERVICE_WIN32;
  1294. Bad3Status.dwCurrentState = SERVICE_START_PENDING;
  1295. Bad3Status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  1296. SERVICE_ACCEPT_PAUSE_CONTINUE;
  1297. Bad3Status.dwWin32ExitCode = 0;
  1298. Bad3Status.dwServiceSpecificExitCode = 0;
  1299. Bad3Status.dwCheckPoint = 1;
  1300. Bad3Status.dwWaitHint = 5000;
  1301. //
  1302. // Register the Control Handler routine.
  1303. //
  1304. DbgPrint(" [BAD3] Getting Ready to call RegisterServiceCtrlHandler\n");
  1305. Bad3StatusHandle = RegisterServiceCtrlHandler(
  1306. TEXT("Bad3"),
  1307. Bad3CtrlHandler);
  1308. if (Bad3StatusHandle == (SERVICE_STATUS_HANDLE)0) {
  1309. DbgPrint(" [BAD3] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  1310. }
  1311. //
  1312. // Return the status
  1313. //
  1314. if (!SetServiceStatus (Bad3StatusHandle, &Bad3Status)) {
  1315. status = GetLastError();
  1316. DbgPrint(" [BAD3] SetServiceStatus error %ld\n",status);
  1317. }
  1318. //
  1319. // Wait forever until we are told to terminate.
  1320. //
  1321. status = WaitForSingleObject (
  1322. Bad3DoneEvent,
  1323. INFINITE_WAIT_TIME);
  1324. DbgPrint(" [BAD3] Leaving the Bad3 service\n");
  1325. CloseHandle(Bad3DoneEvent);
  1326. return(NO_ERROR);
  1327. }
  1328. /****************************************************************************/
  1329. VOID
  1330. Bad3CtrlHandler (
  1331. IN DWORD Opcode
  1332. )
  1333. {
  1334. DbgPrint(" [BAD3] opcode = %ld\n", Opcode);
  1335. //
  1336. // Find and operate on the request.
  1337. //
  1338. switch(Opcode) {
  1339. case SERVICE_CONTROL_PAUSE:
  1340. Bad3Status.dwCurrentState = SERVICE_PAUSED;
  1341. break;
  1342. case SERVICE_CONTROL_CONTINUE:
  1343. Bad3Status.dwCurrentState = SERVICE_RUNNING;
  1344. break;
  1345. case SERVICE_CONTROL_STOP:
  1346. Bad3Status.dwWin32ExitCode = 0;
  1347. Bad3Status.dwServiceSpecificExitCode = 0;
  1348. Bad3Status.dwCurrentState = SERVICE_STOPPED;
  1349. Bad3Status.dwCheckPoint = 1;
  1350. Bad3Status.dwWaitHint = 20000;
  1351. SetEvent(Bad3DoneEvent);
  1352. break;
  1353. case SERVICE_CONTROL_INTERROGATE:
  1354. break;
  1355. default:
  1356. DbgPrint(" [BAD3] Unrecognized opcode %ld\n", Opcode);
  1357. }
  1358. //
  1359. // Don't send a status response.
  1360. //
  1361. #ifdef REMOVE
  1362. if (!SetServiceStatus (Bad3StatusHandle, &Bad3Status)) {
  1363. status = GetLastError();
  1364. DbgPrint(" [BAD3] SetServiceStatus error %ld\n",status);
  1365. }
  1366. #endif
  1367. CloseHandle(Bad3DoneEvent);
  1368. return;
  1369. }
  1370. /****************************************************************************/
  1371. //
  1372. // Bad4 will start normally, but on stop it only sends one stop pending
  1373. // status before it terminates itself without further notification.
  1374. //
  1375. DWORD
  1376. Bad4Start (
  1377. DWORD argc,
  1378. LPTSTR *argv
  1379. )
  1380. {
  1381. DWORD status;
  1382. DWORD i;
  1383. DbgPrint(" [BAD4] Inside the Bad4 Service Thread\n");
  1384. for (i=0; i<argc; i++) {
  1385. DbgPrint(" [BAD4] CommandArg%d = %s\n", i,argv[i]);
  1386. }
  1387. Bad4DoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  1388. //
  1389. // Fill in this services status structure
  1390. //
  1391. Bad4Status.dwServiceType = SERVICE_WIN32;
  1392. Bad4Status.dwCurrentState = SERVICE_RUNNING;
  1393. Bad4Status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  1394. SERVICE_ACCEPT_PAUSE_CONTINUE;
  1395. Bad4Status.dwWin32ExitCode = 0;
  1396. Bad4Status.dwServiceSpecificExitCode = 0;
  1397. Bad4Status.dwCheckPoint = 0;
  1398. Bad4Status.dwWaitHint = 0;
  1399. //
  1400. // Register the Control Handler routine.
  1401. //
  1402. DbgPrint(" [BAD4] Getting Ready to call RegisterServiceCtrlHandler\n");
  1403. Bad4StatusHandle = RegisterServiceCtrlHandler(
  1404. TEXT("Bad4"),
  1405. Bad4CtrlHandler);
  1406. if (Bad4StatusHandle == (SERVICE_STATUS_HANDLE)0) {
  1407. DbgPrint(" [BAD4] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  1408. }
  1409. //
  1410. // Return the status
  1411. //
  1412. if (!SetServiceStatus (Bad4StatusHandle, &Bad4Status)) {
  1413. status = GetLastError();
  1414. DbgPrint(" [BAD4] SetServiceStatus error %ld\n",status);
  1415. }
  1416. //
  1417. // Wait forever until we are told to terminate.
  1418. //
  1419. status = WaitForSingleObject (
  1420. Bad4DoneEvent,
  1421. INFINITE_WAIT_TIME);
  1422. DbgPrint(" [BAD4] Leaving the Bad4 service\n");
  1423. CloseHandle(Bad4DoneEvent);
  1424. return(NO_ERROR);
  1425. }
  1426. /****************************************************************************/
  1427. VOID
  1428. Bad4CtrlHandler (
  1429. IN DWORD Opcode
  1430. )
  1431. {
  1432. DWORD status;
  1433. DbgPrint(" [BAD4] opcode = %ld\n", Opcode);
  1434. //
  1435. // Find and operate on the request.
  1436. //
  1437. switch(Opcode) {
  1438. case SERVICE_CONTROL_PAUSE:
  1439. Bad4Status.dwCurrentState = SERVICE_PAUSED;
  1440. break;
  1441. case SERVICE_CONTROL_CONTINUE:
  1442. Bad4Status.dwCurrentState = SERVICE_RUNNING;
  1443. break;
  1444. case SERVICE_CONTROL_STOP:
  1445. Bad4Status.dwWin32ExitCode = 0;
  1446. Bad4Status.dwServiceSpecificExitCode = 0;
  1447. Bad4Status.dwCurrentState = SERVICE_STOP_PENDING;
  1448. Bad4Status.dwCheckPoint = 1;
  1449. Bad4Status.dwWaitHint = 20000;
  1450. SetEvent(Bad4DoneEvent);
  1451. break;
  1452. case SERVICE_CONTROL_INTERROGATE:
  1453. break;
  1454. default:
  1455. DbgPrint(" [BAD4] Unrecognized opcode %ld\n", Opcode);
  1456. }
  1457. //
  1458. // Send a status response.
  1459. //
  1460. if (!SetServiceStatus (Bad4StatusHandle, &Bad4Status)) {
  1461. status = GetLastError();
  1462. DbgPrint(" [BAD4] SetServiceStatus error %ld\n",status);
  1463. }
  1464. CloseHandle(Bad4DoneEvent);
  1465. return;
  1466. }
  1467. /****************************************************************************/
  1468. //
  1469. // HangOnStop Service doesn't return from the control handling routine
  1470. // on STOP requests until after the pipe timeout period (30 seconds).
  1471. // After 40 seconds, it sends a STOP_PENDING status.
  1472. //
  1473. // Just to confuse things, after the timeout, this service sends a
  1474. // RUNNING status (after an additional 30msec delay). Then it sleeps for
  1475. // 20 seconds before sending a STOPPED status.
  1476. //
  1477. DWORD
  1478. HangOnStopStart (
  1479. DWORD argc,
  1480. LPTSTR *argv
  1481. )
  1482. {
  1483. DWORD status;
  1484. DWORD i;
  1485. DbgPrint(" [HangOnStop] Inside the HangOnStop Service Thread\n");
  1486. for (i=0; i<argc; i++) {
  1487. DbgPrint(" [HangOnStop] CommandArg%d = %s\n", i,argv[i]);
  1488. }
  1489. HangOnStopDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  1490. //
  1491. // Fill in this services status structure
  1492. //
  1493. HangOnStopStatus.dwServiceType = SERVICE_WIN32;
  1494. HangOnStopStatus.dwCurrentState = SERVICE_RUNNING;
  1495. HangOnStopStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  1496. SERVICE_ACCEPT_PAUSE_CONTINUE;
  1497. HangOnStopStatus.dwWin32ExitCode = 0;
  1498. HangOnStopStatus.dwServiceSpecificExitCode = 0;
  1499. HangOnStopStatus.dwCheckPoint = 0;
  1500. HangOnStopStatus.dwWaitHint = 0;
  1501. //
  1502. // Register the Control Handler routine.
  1503. //
  1504. DbgPrint(" [HangOnStop] Getting Ready to call RegisterServiceCtrlHandler\n");
  1505. HangOnStopStatusHandle = RegisterServiceCtrlHandler(
  1506. TEXT("HangOnStop"),
  1507. HangOnStopCtrlHandler);
  1508. if (HangOnStopStatusHandle == (SERVICE_STATUS_HANDLE)0) {
  1509. DbgPrint(" [HangOnStop] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  1510. }
  1511. //
  1512. // Return the status
  1513. //
  1514. if (!SetServiceStatus (HangOnStopStatusHandle, &HangOnStopStatus)) {
  1515. status = GetLastError();
  1516. DbgPrint(" [HangOnStop] SetServiceStatus error %ld\n",status);
  1517. }
  1518. //
  1519. // Wait forever until we are told to terminate.
  1520. //
  1521. status = WaitForSingleObject (
  1522. HangOnStopDoneEvent,
  1523. INFINITE_WAIT_TIME);
  1524. Sleep(30);
  1525. HangOnStopStatus.dwCurrentState = SERVICE_RUNNING;
  1526. if (!SetServiceStatus (HangOnStopStatusHandle, &HangOnStopStatus)) {
  1527. status = GetLastError();
  1528. DbgPrint(" [HangOnStop] SetServiceStatus error %ld\n",status);
  1529. }
  1530. Sleep(20000);
  1531. HangOnStopStatus.dwCurrentState = SERVICE_STOPPED;
  1532. if (!SetServiceStatus (HangOnStopStatusHandle, &HangOnStopStatus)) {
  1533. status = GetLastError();
  1534. DbgPrint(" [HangOnStop] SetServiceStatus error %ld\n",status);
  1535. }
  1536. DbgPrint(" [HangOnStop] Leaving the HangOnStop service\n");
  1537. CloseHandle(HangOnStopDoneEvent);
  1538. return(NO_ERROR);
  1539. }
  1540. /****************************************************************************/
  1541. VOID
  1542. HangOnStopCtrlHandler (
  1543. IN DWORD Opcode
  1544. )
  1545. {
  1546. DWORD status;
  1547. DbgPrint(" [HangOnStop] opcode = %ld\n", Opcode);
  1548. //
  1549. // Find and operate on the request.
  1550. //
  1551. switch(Opcode) {
  1552. case SERVICE_CONTROL_PAUSE:
  1553. HangOnStopStatus.dwCurrentState = SERVICE_PAUSED;
  1554. break;
  1555. case SERVICE_CONTROL_CONTINUE:
  1556. HangOnStopStatus.dwCurrentState = SERVICE_RUNNING;
  1557. break;
  1558. case SERVICE_CONTROL_STOP:
  1559. HangOnStopStatus.dwWin32ExitCode = 0;
  1560. HangOnStopStatus.dwServiceSpecificExitCode = 0;
  1561. HangOnStopStatus.dwCurrentState = SERVICE_STOP_PENDING;
  1562. HangOnStopStatus.dwCheckPoint = 1;
  1563. HangOnStopStatus.dwWaitHint = 20000;
  1564. Sleep(40000);
  1565. SetEvent(HangOnStopDoneEvent);
  1566. break;
  1567. case SERVICE_CONTROL_INTERROGATE:
  1568. break;
  1569. default:
  1570. DbgPrint(" [HangOnStop] Unrecognized opcode %ld\n", Opcode);
  1571. }
  1572. //
  1573. // Send a status response.
  1574. //
  1575. if (!SetServiceStatus (HangOnStopStatusHandle, &HangOnStopStatus)) {
  1576. status = GetLastError();
  1577. DbgPrint(" [HangOnStop] SetServiceStatus error %ld\n",status);
  1578. }
  1579. CloseHandle(HangOnStopDoneEvent);
  1580. return;
  1581. }
  1582. /****************************************************************************/
  1583. DWORD
  1584. StartProcStart (
  1585. DWORD argc,
  1586. LPTSTR *argv
  1587. )
  1588. {
  1589. DWORD status;
  1590. DWORD i;
  1591. STARTUPINFOW ScStartupInfo;
  1592. PROCESS_INFORMATION processInfo;
  1593. LPWSTR ImageName;
  1594. HWND hWnd= NULL;
  1595. DbgPrint(" [START_PROC] Inside the StartProc Service Thread\n");
  1596. for (i=0; i<argc; i++) {
  1597. DbgPrint(" [START_PROC] CommandArg%d = %s\n", i,argv[i]);
  1598. }
  1599. //
  1600. // This call to a GDI function causes a connection to the Win
  1601. // User Server. It doesn't matter which GDI function is called, this
  1602. // one happens to be easiest. This allows us to create a child process
  1603. // that is interactive with the user (like cmd.exe).
  1604. //
  1605. hWnd = GetDesktopWindow();
  1606. if (hWnd == NULL) {
  1607. DbgPrint(" [START_PROC] GetDesktopWindow call failed %d\n", GetLastError());
  1608. }
  1609. //
  1610. // Create an event to wait on.
  1611. //
  1612. StartProcDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  1613. //
  1614. // Fill in this services status structure
  1615. //
  1616. StartProcStatus.dwServiceType = SERVICE_WIN32;
  1617. StartProcStatus.dwCurrentState = SERVICE_RUNNING;
  1618. StartProcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  1619. SERVICE_ACCEPT_PAUSE_CONTINUE |
  1620. SERVICE_ACCEPT_SHUTDOWN;
  1621. StartProcStatus.dwWin32ExitCode = 0;
  1622. StartProcStatus.dwServiceSpecificExitCode = 0;
  1623. StartProcStatus.dwCheckPoint = 0;
  1624. StartProcStatus.dwWaitHint = 0;
  1625. //
  1626. // Register the Control Handler routine.
  1627. //
  1628. DbgPrint(" [START_PROC] Getting Ready to call RegisterServiceCtrlHandler\n");
  1629. StartProcStatusHandle = RegisterServiceCtrlHandler(
  1630. TEXT("StartProc"),
  1631. StartProcCtrlHandler);
  1632. if (StartProcStatusHandle == (SERVICE_STATUS_HANDLE)0) {
  1633. DbgPrint(" [START_PROC] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  1634. }
  1635. //
  1636. // Return the status
  1637. //
  1638. if (!SetServiceStatus (StartProcStatusHandle, &StartProcStatus)) {
  1639. status = GetLastError();
  1640. DbgPrint(" [START_PROC] SetServiceStatus error %ld\n",status);
  1641. }
  1642. //*******************************************************************
  1643. // Start a Child Process
  1644. //
  1645. ScStartupInfo.cb = sizeof(STARTUPINFOW); // size
  1646. ScStartupInfo.lpReserved = NULL; // lpReserved
  1647. ScStartupInfo.lpDesktop = NULL; // DeskTop
  1648. ScStartupInfo.lpTitle = L"Local System Window"; // Title
  1649. ScStartupInfo.dwX = 0; // X (position)
  1650. ScStartupInfo.dwY = 0; // Y (position)
  1651. ScStartupInfo.dwXSize = 0; // XSize (dimension)
  1652. ScStartupInfo.dwYSize = 0; // YSize (dimension)
  1653. ScStartupInfo.dwXCountChars = 0; // XCountChars
  1654. ScStartupInfo.dwYCountChars = 0; // YCountChars
  1655. ScStartupInfo.dwFillAttribute = 0; // FillAttributes
  1656. ScStartupInfo.dwFlags = STARTF_FORCEOFFFEEDBACK;
  1657. // Flags - should be STARTF_TASKNOTCLOSABLE
  1658. ScStartupInfo.wShowWindow = SW_SHOWNORMAL; // ShowWindow
  1659. ScStartupInfo.cbReserved2 = 0L; // cbReserved
  1660. ScStartupInfo.lpReserved2 = NULL; // lpReserved
  1661. // ScStartupInfo.dwFlags |= STARTF_DESKTOPINHERIT;
  1662. // ScStartupInfo.lpDesktop = pszInteractiveDesktop;
  1663. ImageName = L"cmd.exe";
  1664. if (!CreateProcessW (
  1665. NULL, // Fully qualified image name
  1666. ImageName, // Command Line
  1667. NULL, // Process Attributes
  1668. NULL, // Thread Attributes
  1669. TRUE, // Inherit Handles
  1670. CREATE_NEW_CONSOLE, // Creation Flags
  1671. NULL, // Pointer to Environment block
  1672. NULL, // Pointer to Current Directory
  1673. &ScStartupInfo, // Startup Info
  1674. &processInfo) // ProcessInformation
  1675. ) {
  1676. status = GetLastError();
  1677. DbgPrint(" [START_PROC] CreateProcess %ws failed %d \n",
  1678. ImageName,
  1679. status);
  1680. }
  1681. else {
  1682. DbgPrint(" [START_PROC]CreateProcess Success \n");
  1683. }
  1684. //
  1685. //
  1686. //*******************************************************************
  1687. //
  1688. // Wait forever until we are told to terminate.
  1689. //
  1690. status = WaitForSingleObject (
  1691. StartProcDoneEvent,
  1692. INFINITE_WAIT_TIME);
  1693. DbgPrint(" [START_PROC] Leaving the StartProc service\n");
  1694. CloseHandle(StartProcDoneEvent);
  1695. CloseHandle(hWnd);
  1696. return(NO_ERROR);
  1697. }
  1698. /****************************************************************************/
  1699. VOID
  1700. StartProcCtrlHandler (
  1701. IN DWORD Opcode
  1702. )
  1703. {
  1704. DWORD status;
  1705. DbgPrint(" [START_PROC] opcode = %ld\n", Opcode);
  1706. //
  1707. // Find and operate on the request.
  1708. //
  1709. switch(Opcode) {
  1710. case SERVICE_CONTROL_PAUSE:
  1711. StartProcStatus.dwCurrentState = SERVICE_PAUSED;
  1712. break;
  1713. case SERVICE_CONTROL_CONTINUE:
  1714. StartProcStatus.dwCurrentState = SERVICE_RUNNING;
  1715. break;
  1716. case SERVICE_CONTROL_SHUTDOWN:
  1717. case SERVICE_CONTROL_STOP:
  1718. StartProcStatus.dwWin32ExitCode = 0;
  1719. StartProcStatus.dwCurrentState = SERVICE_STOPPED;
  1720. SetEvent(StartProcDoneEvent);
  1721. break;
  1722. case SERVICE_CONTROL_INTERROGATE:
  1723. break;
  1724. default:
  1725. DbgPrint(" [START_PROC] Unrecognized opcode %ld\n", Opcode);
  1726. }
  1727. //
  1728. // Send a status response.
  1729. //
  1730. if (!SetServiceStatus (StartProcStatusHandle, &StartProcStatus)) {
  1731. status = GetLastError();
  1732. DbgPrint(" [START_PROC] SetServiceStatus error %ld\n",status);
  1733. }
  1734. return;
  1735. }
  1736. /****************************************************************************/
  1737. DWORD
  1738. StartAndDieStart (
  1739. DWORD argc,
  1740. LPTSTR *argv
  1741. )
  1742. {
  1743. DWORD status;
  1744. DWORD i;
  1745. DWORD checkpoint=1;
  1746. DbgPrint(" [StartAndDie] Inside the StartAndDie Service Thread\n");
  1747. for (i=0; i<argc; i++) {
  1748. DbgPrint(" [START&DIE] CommandArg%d = %s\n", i,argv[i]);
  1749. }
  1750. StartAndDieDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  1751. //
  1752. // Fill in this services status structure
  1753. //
  1754. StartAndDieStatus.dwServiceType = SERVICE_WIN32;
  1755. StartAndDieStatus.dwCurrentState = SERVICE_START_PENDING;
  1756. StartAndDieStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  1757. SERVICE_ACCEPT_PAUSE_CONTINUE |
  1758. SERVICE_ACCEPT_SHUTDOWN;
  1759. StartAndDieStatus.dwWin32ExitCode = 0;
  1760. StartAndDieStatus.dwServiceSpecificExitCode = 0;
  1761. StartAndDieStatus.dwCheckPoint = checkpoint++;
  1762. StartAndDieStatus.dwWaitHint = 40000;
  1763. //
  1764. // Register the Control Handler routine.
  1765. //
  1766. DbgPrint(" [START&DIE] Getting Ready to call RegisterServiceCtrlHandler\n");
  1767. StartAndDieStatusHandle = RegisterServiceCtrlHandler(
  1768. TEXT("StartAndDie"),
  1769. StartAndDieCtrlHandler);
  1770. if (StartAndDieStatusHandle == (SERVICE_STATUS_HANDLE)0) {
  1771. DbgPrint(" [START&DIE] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  1772. }
  1773. //
  1774. // Return the status
  1775. //
  1776. if (!SetServiceStatus (StartAndDieStatusHandle, &StartAndDieStatus)) {
  1777. status = GetLastError();
  1778. DbgPrint(" [START&DIE] SetServiceStatus error %ld\n",status);
  1779. }
  1780. //
  1781. // Sleep for a bit, the say we are running, then say we are stopped.
  1782. //
  1783. Sleep(30000);
  1784. StartAndDieStatus.dwCurrentState = SERVICE_RUNNING;
  1785. StartAndDieStatus.dwCheckPoint = 0;
  1786. StartAndDieStatus.dwWaitHint = 0;
  1787. if (!SetServiceStatus (StartAndDieStatusHandle, &StartAndDieStatus)) {
  1788. status = GetLastError();
  1789. DbgPrint("[START&DIE] SetServiceStatus error %ld\n",status);
  1790. }
  1791. StartAndDieStatus.dwCurrentState = SERVICE_STOPPED;
  1792. StartAndDieStatus.dwCheckPoint = 0;
  1793. StartAndDieStatus.dwWaitHint = 0;
  1794. StartAndDieStatus.dwWin32ExitCode = ERROR_INVALID_ENVIRONMENT;
  1795. if (!SetServiceStatus (StartAndDieStatusHandle, &StartAndDieStatus)) {
  1796. status = GetLastError();
  1797. DbgPrint("[START&DIE] SetServiceStatus error %ld\n",status);
  1798. }
  1799. DbgPrint(" [START&DIE] Leaving the start&die service\n");
  1800. CloseHandle(StartAndDieDoneEvent);
  1801. return(NO_ERROR);
  1802. }
  1803. /****************************************************************************/
  1804. VOID
  1805. StartAndDieCtrlHandler (
  1806. IN DWORD Opcode
  1807. )
  1808. {
  1809. DWORD status;
  1810. DbgPrint(" [START&DIE] opcode = %ld\n", Opcode);
  1811. //
  1812. // Find and operate on the request.
  1813. //
  1814. switch(Opcode) {
  1815. case SERVICE_CONTROL_PAUSE:
  1816. SvcPrintf("StartAndDie received a PAUSE\n");
  1817. StartAndDieStatus.dwCurrentState = SERVICE_PAUSED;
  1818. break;
  1819. case SERVICE_CONTROL_CONTINUE:
  1820. SvcPrintf("StartAndDie received a CONTINUE\n");
  1821. StartAndDieStatus.dwCurrentState = SERVICE_RUNNING;
  1822. break;
  1823. case SERVICE_CONTROL_SHUTDOWN:
  1824. case SERVICE_CONTROL_STOP:
  1825. SvcPrintf("StartAndDie received a STOP\n");
  1826. StartAndDieStatus.dwWin32ExitCode = 0;
  1827. StartAndDieStatus.dwCurrentState = SERVICE_STOPPED;
  1828. SetEvent(StartAndDieDoneEvent);
  1829. break;
  1830. case SERVICE_CONTROL_INTERROGATE:
  1831. SvcPrintf("StartAndDie received an INTERROGATE\n");
  1832. break;
  1833. default:
  1834. DbgPrint(" [START&DIE] Unrecognized opcode %ld\n", Opcode);
  1835. }
  1836. //
  1837. // Send a status response.
  1838. //
  1839. if (!SetServiceStatus (StartAndDieStatusHandle, &StartAndDieStatus)) {
  1840. status = GetLastError();
  1841. DbgPrint(" [START&DIE] SetServiceStatus error %ld\n",status);
  1842. }
  1843. return;
  1844. }
  1845. VOID
  1846. SetUpConsole()
  1847. {
  1848. //#ifdef NOT_NECESSARY
  1849. CONSOLE_SCREEN_BUFFER_INFO csbi;
  1850. COORD coord;
  1851. HANDLE consoleHandle=NULL;
  1852. if (!AllocConsole()) {
  1853. DbgPrint("[TS2]AllocConsole failed %d\n",GetLastError());
  1854. }
  1855. consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
  1856. if (consoleHandle == NULL) {
  1857. DbgPrint("[TS2]GetStdHandle failed %d\n",GetLastError());
  1858. }
  1859. if (!GetConsoleScreenBufferInfo(
  1860. GetStdHandle(STD_OUTPUT_HANDLE),
  1861. &csbi)) {
  1862. DbgPrint("[TS2]GetConsoleScreenBufferInfo failed %d\n",GetLastError());
  1863. }
  1864. coord.X = (SHORT)(csbi.srWindow.Right - csbi.srWindow.Left + 1);
  1865. coord.Y = (SHORT)((csbi.srWindow.Bottom - csbi.srWindow.Top + 1) * 20);
  1866. if (!SetConsoleScreenBufferSize(
  1867. GetStdHandle(STD_OUTPUT_HANDLE),
  1868. coord)) {
  1869. DbgPrint("[TS2]SetConsoleScreenBufferSize failed %d\n",GetLastError());
  1870. }
  1871. //#endif //NOT_NECESSARY
  1872. DbgLogFileHandle = CreateFile("\\trace.log",
  1873. GENERIC_READ | GENERIC_WRITE,
  1874. FILE_SHARE_READ,
  1875. NULL,
  1876. CREATE_ALWAYS,
  1877. 0,
  1878. NULL);
  1879. }
  1880. VOID
  1881. SvcPrintf (
  1882. char *Format,
  1883. ...
  1884. )
  1885. /*++
  1886. Routine Description:
  1887. This routine provides printf functionality when the service is run with
  1888. REMOTE.EXE.
  1889. sc config LUMPY binpath= "remote /s \"ts2\" LUMPY"
  1890. NOTE: It is not necessary to allocate a console in this case because
  1891. remote already provides one. So the only portion of SetupConsole() that
  1892. is used is the portion the opens the debug dump file.
  1893. Arguments:
  1894. Same as printf
  1895. Return Value:
  1896. --*/
  1897. {
  1898. va_list arglist;
  1899. char OutputBuffer[1024];
  1900. ULONG length;
  1901. va_start( arglist, Format );
  1902. vsprintf( OutputBuffer, Format, arglist );
  1903. va_end( arglist );
  1904. length = strlen( OutputBuffer );
  1905. if (!WriteFile(
  1906. GetStdHandle(STD_OUTPUT_HANDLE),
  1907. (LPVOID )OutputBuffer,
  1908. length,
  1909. &length,
  1910. NULL )) {
  1911. DbgPrint("[TS2]WriteFile Failed %d \n",GetLastError());
  1912. }
  1913. if(DbgLogFileHandle != INVALID_HANDLE_VALUE) {
  1914. if (!WriteFile(
  1915. DbgLogFileHandle,
  1916. (LPVOID )OutputBuffer,
  1917. length,
  1918. &length,
  1919. NULL )) {
  1920. DbgPrint("[TS2]WriteFile Failed %d \n",GetLastError());
  1921. }
  1922. }
  1923. } // SsPrintf