|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
ts2.c
Abstract:
This is a test program for exercising the service controller. This program acts like a service and exercises the Service Controller API that can be called from a service: NetServiceStartCtrlDispatcher NetServiceRegisterCtrlHandler NetServiceStatus
Contents: Grumpy Lumpy Dumpy Sleepy Dead SlowStop - Takes a long time to stop based on Message Box. Terminate - Starts normally, After 20 seconds, it sends a STOPPED status, and does an ExitProcess. Bad1 - Never calls RegisterServiceCtrlHandler. Bad2 - Stays in START_PENDING forever. Bad3 - Start= Sends 1 START_PENDING, then doesn't send any further status messages. Otherwise operates normally. Bad4 - Normal Start; On Stop it sends 1 stop pending status then terminates itself. HangOnStop - Doesn't return from CtrlHandl routine on Stop requests until 40 seconds has passed. (pipe timeout is 30 sec). Sends a RUNNING status after the 40 second wait, then it sleeps for 20 seconds before sending STOPPED status. StartAndDie - Takes 40 seconds to start, then it terminates right after saying it was started.
Author:
Dan Lafferty (danl) 12 Apr-1991
Environment:
User Mode -Win32
Notes:
optional-notes
Revision History:
--*/
//
// Includes
//
#include <nt.h> // DbgPrint prototype
#include <ntrtl.h> // DbgPrint prototype
#include <windef.h>
#include <nturtl.h> // needed for winbase.h
#include <winbase.h>
#include <wingdi.h> // for winuserp.h
#include <winuser.h> // MessageBox
#include <winuserp.h> // STARTF_DESKTOPINHERIT
#include <wincon.h> // CONSOLE_SCREEN_BUFFER_INFO
#include <winsvc.h>
#include <tstr.h> // Unicode string macros
#include <stdio.h> // printf
//
// Defines
//
#define INFINITE_WAIT_TIME 0xffffffff
#define NULL_STRING TEXT("");
LPWSTR pszInteractiveDesktop=L"WinSta0\\Default";
//
// Globals
//
HANDLE DbgLogFileHandle = INVALID_HANDLE_VALUE;
SERVICE_STATUS GrumpyStatus; SERVICE_STATUS LumpyStatus; SERVICE_STATUS DumpyStatus; SERVICE_STATUS SleepyStatus; SERVICE_STATUS DeadStatus; SERVICE_STATUS SlowStopStatus; SERVICE_STATUS TerminateStatus; SERVICE_STATUS Bad1Status; SERVICE_STATUS Bad2Status; SERVICE_STATUS Bad3Status; SERVICE_STATUS Bad4Status; SERVICE_STATUS HangOnStopStatus; SERVICE_STATUS StartProcStatus; SERVICE_STATUS StartAndDieStatus;
HANDLE GrumpyDoneEvent; HANDLE LumpyDoneEvent; HANDLE DumpyDoneEvent; HANDLE SleepyDoneEvent; HANDLE DeadDoneEvent; HANDLE SlowStopDoneEvent; HANDLE TerminateDoneEvent; HANDLE Bad1DoneEvent; HANDLE Bad2DoneEvent; HANDLE Bad3DoneEvent; HANDLE Bad4DoneEvent; HANDLE HangOnStopDoneEvent; HANDLE StartProcDoneEvent; HANDLE StartAndDieDoneEvent;
SERVICE_STATUS_HANDLE GrumpyStatusHandle; SERVICE_STATUS_HANDLE LumpyStatusHandle; SERVICE_STATUS_HANDLE DumpyStatusHandle; SERVICE_STATUS_HANDLE SleepyStatusHandle; SERVICE_STATUS_HANDLE DeadStatusHandle; SERVICE_STATUS_HANDLE SlowStopStatusHandle; SERVICE_STATUS_HANDLE TerminateStatusHandle; SERVICE_STATUS_HANDLE Bad1StatusHandle; SERVICE_STATUS_HANDLE Bad2StatusHandle; SERVICE_STATUS_HANDLE Bad3StatusHandle; SERVICE_STATUS_HANDLE Bad4StatusHandle; SERVICE_STATUS_HANDLE HangOnStopStatusHandle; SERVICE_STATUS_HANDLE StartProcStatusHandle; SERVICE_STATUS_HANDLE StartAndDieStatusHandle;
//
// Function Prototypes
//
DWORD GrumpyStart ( DWORD argc, LPTSTR *argv );
DWORD LumpyStart ( DWORD argc, LPTSTR *argv );
DWORD DumpyStart ( DWORD argc, LPTSTR *argv );
DWORD SleepyStart ( DWORD argc, LPTSTR *argv );
DWORD DeadStart ( DWORD argc, LPTSTR *argv );
DWORD SlowStopStart ( DWORD argc, LPTSTR *argv );
DWORD TerminateStart ( DWORD argc, LPTSTR *argv );
DWORD Bad1Start (DWORD argc,LPTSTR *argv);
DWORD Bad2Start (DWORD argc,LPTSTR *argv);
DWORD Bad3Start (DWORD argc,LPTSTR *argv);
DWORD Bad4Start (DWORD argc,LPTSTR *argv);
DWORD HangOnStopStart (DWORD argc,LPTSTR *argv);
DWORD StartProcStart (DWORD argc,LPTSTR *argv);
DWORD StartAndDieStart (DWORD argc,LPTSTR *argv);
VOID GrumpyCtrlHandler ( IN DWORD opcode );
VOID LumpyCtrlHandler ( IN DWORD opcode );
VOID DumpyCtrlHandler ( IN DWORD opcode );
VOID SleepyCtrlHandler ( IN DWORD opcode );
VOID DeadCtrlHandler ( IN DWORD opcode );
VOID SlowStopCtrlHandler ( IN DWORD opcode );
VOID TerminateCtrlHandler ( IN DWORD opcode );
VOID Bad1CtrlHandler (IN DWORD opcode);
VOID Bad2CtrlHandler (IN DWORD opcode);
VOID Bad3CtrlHandler (IN DWORD opcode);
VOID Bad4CtrlHandler (IN DWORD opcode);
VOID HangOnStopCtrlHandler (IN DWORD opcode);
VOID StartProcCtrlHandler (IN DWORD opcode);
VOID StartAndDieCtrlHandler (IN DWORD opcode);
VOID SvcPrintf (char *Format, ...);
VOID SetUpConsole();
/****************************************************************************/ VOID __cdecl main ( DWORD argc, PCHAR argv[] ) { DWORD i;
SERVICE_TABLE_ENTRY DispatchTable[] = { { TEXT("StartProc"), StartProcStart }, { TEXT("grumpy"), GrumpyStart }, { TEXT("lumpy"), LumpyStart }, { TEXT("dumpy"), DumpyStart }, { TEXT("sleepy"), SleepyStart }, { TEXT("dead"), DeadStart }, { TEXT("slowstop"), SlowStopStart }, { TEXT("terminate"), TerminateStart }, { TEXT("Bad1"), Bad1Start }, { TEXT("Bad2"), Bad2Start }, { TEXT("Bad3"), Bad3Start }, { TEXT("Bad4"), Bad4Start }, { TEXT("HangOnStop"), HangOnStopStart }, { TEXT("StartAndDie"), StartAndDieStart }, { NULL, NULL } };
DbgPrint("[ts2]Args passed to .exe main() function:\n"); for (i=0; i<argc; i++) { DbgPrint(" [TS2] CommandArg%d = %s\n", i,argv[i]); }
//SetUpConsole();
if (!StartServiceCtrlDispatcher( DispatchTable)) { DbgPrint("[ts2]StartServiceCtrlDispatcher returned error %d\n",GetLastError); }
DbgPrint("[ts2]The Service Process is Terminating....\n");
ExitProcess(0);
}
/****************************************************************************/
//
// Grumpy will take a long time to respond to pause
//
//
DWORD GrumpyStart ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i; //---------------------------------------------------------------------
SC_HANDLE SCHandle; SC_HANDLE ServiceHandle; //---------------------------------------------------------------------
DbgPrint(" [GRUMPY] Inside the Grumpy Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [GRUMPY] CommandArg%d = %s\n", i,argv[i]); }
GrumpyDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
GrumpyStatus.dwServiceType = SERVICE_WIN32; GrumpyStatus.dwCurrentState = SERVICE_RUNNING; GrumpyStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
//
// Set up bogus values for status.
//
GrumpyStatus.dwWin32ExitCode = 14; GrumpyStatus.dwServiceSpecificExitCode = 55; GrumpyStatus.dwCheckPoint = 53; GrumpyStatus.dwWaitHint = 22;
//
// Register the Control Handler routine.
//
DbgPrint(" [GRUMPY] Getting Ready to call RegisterServiceCtrlHandler\n");
GrumpyStatusHandle = RegisterServiceCtrlHandler( TEXT("grumpy"), GrumpyCtrlHandler);
if (GrumpyStatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [GRUMPY] RegisterServiceCtrlHandler failed %d\n", GetLastError()); }
//
// Return the status
//
if (!SetServiceStatus (GrumpyStatusHandle, &GrumpyStatus)) { status = GetLastError(); DbgPrint(" [GRUMPY] SetServiceStatus error %ld\n",status); }
#define START_SERVICE
#ifdef START_SERVICE
//---------------------------------------------------------------------
//
// TEMP CODE - Start another service
//
DbgPrint("[GRUMPY] Attempt to start Messinger"); if ((SCHandle = OpenSCManager(NULL,NULL,SC_MANAGER_CONNECT))!= NULL) { if ((ServiceHandle = OpenService( SCHandle, TEXT("Messinger"), SERVICE_START)) != NULL) {
if (!StartService(ServiceHandle,0,NULL)) { DbgPrint("[GRUMPY] StartService Failed, rc = %d", GetLastError()); } } else { DbgPrint("GRUMPY] OpenService failed %d\n",GetLastError()); } } else { DbgPrint("GRUMPY] OpenSCManager failed %d\n",GetLastError()); } //
//
//
//---------------------------------------------------------------------
#endif
//
// Wait forever until we are told to terminate.
//
status = WaitForSingleObject ( GrumpyDoneEvent, INFINITE_WAIT_TIME);
DbgPrint(" [GRUMPY] Leaving the grumpy service\n");
CloseHandle(GrumpyDoneEvent); return(NO_ERROR); }
/****************************************************************************/ VOID GrumpyCtrlHandler ( IN DWORD Opcode ) {
DWORD status;
DbgPrint(" [GRUMPY] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE:
Sleep(60000); // 1 minute
GrumpyStatus.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE:
GrumpyStatus.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_STOP:
GrumpyStatus.dwWin32ExitCode = 0; GrumpyStatus.dwServiceSpecificExitCode = 0; GrumpyStatus.dwCurrentState = SERVICE_STOPPED; GrumpyStatus.dwWaitHint = 0; GrumpyStatus.dwCheckPoint = 0;
SetEvent(GrumpyDoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: //
// Send a BAD Status Response
//
DbgPrint(" [GRUMPY] Sending bogus status (0x00000000)\n"); if (!SetServiceStatus (0L, &GrumpyStatus)) { status = GetLastError(); DbgPrint(" [GRUMPY] SetServiceStatus error %ld " " - - Expect %d\n",status,ERROR_INVALID_HANDLE); }
DbgPrint(" [GRUMPY] Sending bogus status (0xefefefef)\n"); if (!SetServiceStatus (0xefefefef, &GrumpyStatus)) { status = GetLastError(); DbgPrint(" [GRUMPY] SetServiceStatus error %ld " " - - Expect %d\n",status,ERROR_INVALID_HANDLE); } break;
default: DbgPrint(" [GRUMPY] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (GrumpyStatusHandle, &GrumpyStatus)) { status = GetLastError(); DbgPrint(" [GRUMPY] SetServiceStatus error %ld\n",status); } return; }
/****************************************************************************/ DWORD LumpyStart ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i;
DbgPrint(" [LUMPY] Inside the Lumpy Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [LUMPY] CommandArg%d = %s\n", i,argv[i]); }
LumpyDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
LumpyStatus.dwServiceType = SERVICE_WIN32|SERVICE_INTERACTIVE_PROCESS; LumpyStatus.dwCurrentState = SERVICE_RUNNING; LumpyStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN; LumpyStatus.dwWin32ExitCode = 0; LumpyStatus.dwServiceSpecificExitCode = 0; LumpyStatus.dwCheckPoint = 0; LumpyStatus.dwWaitHint = 0;
//
// Register the Control Handler routine.
//
DbgPrint(" [LUMPY] Getting Ready to call RegisterServiceCtrlHandler\n");
LumpyStatusHandle = RegisterServiceCtrlHandler( TEXT("lumpy"), LumpyCtrlHandler);
if (LumpyStatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [LUMPY] RegisterServiceCtrlHandler failed %d\n", GetLastError()); }
//
// Return the status
//
if (!SetServiceStatus (LumpyStatusHandle, &LumpyStatus)) { status = GetLastError(); DbgPrint(" [LUMPY] SetServiceStatus error %ld\n",status); }
//
// Wait forever until we are told to terminate.
//
status = WaitForSingleObject ( LumpyDoneEvent, INFINITE_WAIT_TIME);
if (status == WAIT_FAILED) { DbgPrint(" [LUMPY] WaitLastError = %d\n",GetLastError()); }
DbgPrint(" [LUMPY] Leaving the lumpy service\n");
CloseHandle(LumpyDoneEvent); return(NO_ERROR); }
/****************************************************************************/ VOID LumpyCtrlHandler ( IN DWORD Opcode ) {
DWORD status;
DbgPrint(" [LUMPY] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE: SvcPrintf("Lumpy received a PAUSE\n"); LumpyStatus.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE: SvcPrintf("Lumpy received a CONTINUE\n"); LumpyStatus.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_STOP: SvcPrintf("Lumpy received a STOP\n");
LumpyStatus.dwWin32ExitCode = 0; LumpyStatus.dwCurrentState = SERVICE_STOPPED;
if (!SetEvent(LumpyDoneEvent)) { DbgPrint(" [LUMPY] SetEvent Failed %d\n",GetLastError()); } break;
case SERVICE_CONTROL_INTERROGATE: SvcPrintf("Lumpy received an INTERROGATE\n"); break;
default: DbgPrint(" [LUMPY] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (LumpyStatusHandle, &LumpyStatus)) { status = GetLastError(); DbgPrint(" [LUMPY] SetServiceStatus error %ld\n",status); } return; }
/****************************************************************************/ DWORD DumpyStart ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i;
DbgPrint(" [DUMPY] Inside the Dumpy Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [DUMPY] CommandArg%d = %s\n", i,argv[i]); }
DumpyDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
DumpyStatus.dwServiceType = SERVICE_WIN32; DumpyStatus.dwCurrentState = SERVICE_RUNNING; DumpyStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; DumpyStatus.dwWin32ExitCode = 0; DumpyStatus.dwServiceSpecificExitCode = 0; DumpyStatus.dwCheckPoint = 0; DumpyStatus.dwWaitHint = 0;
//
// Register the Control Handler routine.
//
DbgPrint(" [DUMPY] Getting Ready to call RegisterServiceCtrlHandler\n");
DumpyStatusHandle = RegisterServiceCtrlHandler( TEXT("dumpy"), DumpyCtrlHandler);
if (DumpyStatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [DUMPY] RegisterServiceCtrlHandler failed %d\n", GetLastError()); }
//
// Return the status
//
if (!SetServiceStatus (DumpyStatusHandle, &DumpyStatus)) { status = GetLastError(); DbgPrint(" [DUMPY] SetServiceStatus error %ld\n",status); }
//
// Wait forever until we are told to terminate.
//
status = WaitForSingleObject ( DumpyDoneEvent, INFINITE_WAIT_TIME);
DbgPrint(" [DUMPY] Leaving the dumpy service\n");
CloseHandle(DumpyDoneEvent); return(NO_ERROR); }
/****************************************************************************/ VOID DumpyCtrlHandler ( IN DWORD Opcode ) {
DWORD status;
DbgPrint(" [DUMPY] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE:
DumpyStatus.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE:
DumpyStatus.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_STOP:
DumpyStatus.dwWin32ExitCode = 0; DumpyStatus.dwCurrentState = SERVICE_STOPPED;
SetEvent(DumpyDoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: break;
default: DbgPrint(" [DUMPY] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (DumpyStatusHandle, &DumpyStatus)) { status = GetLastError(); DbgPrint(" [DUMPY] SetServiceStatus error %ld\n",status); } return; }
/****************************************************************************/ DWORD SleepyStart ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i; DWORD checkpoint=1;
DbgPrint(" [SLEEPY] Inside the Sleepy Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [SLEEPY] CommandArg%d = %s\n", i,argv[i]); }
SleepyDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
SleepyStatus.dwServiceType = SERVICE_WIN32; SleepyStatus.dwCurrentState = SERVICE_START_PENDING; SleepyStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; SleepyStatus.dwWin32ExitCode = 0; SleepyStatus.dwServiceSpecificExitCode = 0; SleepyStatus.dwCheckPoint = checkpoint++; SleepyStatus.dwWaitHint = 40000;
//
// Register the Control Handler routine.
//
DbgPrint(" [SLEEPY] Getting Ready to call RegisterServiceCtrlHandler\n");
SleepyStatusHandle = RegisterServiceCtrlHandler( TEXT("sleepy"), SleepyCtrlHandler);
if (SleepyStatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [SLEEPY] RegisterServiceCtrlHandler failed %d\n", GetLastError()); }
//
// This service tests the install pending system in the service
// controller. Therefore, it loops and sleeps 4 times prior to
// indicating that installation is complete.
//
for (i=0; i<5; i++) { //
// Return the status
//
DbgPrint(" [SLEEPY] sending install status #%d\n",i); if (!SetServiceStatus (SleepyStatusHandle, &SleepyStatus)) { status = GetLastError(); DbgPrint(" [SLEEPY] SetServiceStatus error %ld\n",status); }
Sleep(20000); // Sleep for 20 seconds
status = WaitForSingleObject ( SleepyDoneEvent, 0); if (status == 0) { DbgPrint(" [SLEEPY] terminated while installing\n"); return(NO_ERROR); }
//
// Increment the checkpoint value in status. (20 seconds)
//
SleepyStatus.dwCheckPoint = checkpoint++; SleepyStatus.dwWaitHint = 40000; DbgPrint(" [SLEEPY] checkpoint = 0x%lx\n",SleepyStatus.dwCheckPoint);
#ifdef SpecialTest
//
//******************************************************************
// TEST out the condition where we have an unsolicited uninstall
// after sending the first status message.
//
SleepyStatus.dwWin32ExitCode = 0; SleepyStatus.dwCurrentState = SERVICE_STOPPED;
if (!SetServiceStatus (SleepyStatusHandle, &SleepyStatus)) { status = GetLastError(); DbgPrint("[SLEEPY] Error From SetServiceStatus %d\n",status); } DbgPrint(" [SLEEPY] Leaving the Sleepy service\n");
return(NO_ERROR);
//
//******************************************************************
#endif //SpecialTest
}
DbgPrint(" [SLEEPY] setting up installed status\n");
SleepyStatus.dwCurrentState = SERVICE_RUNNING; SleepyStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; SleepyStatus.dwWin32ExitCode = 0; SleepyStatus.dwServiceSpecificExitCode = 0; SleepyStatus.dwCheckPoint = 0; SleepyStatus.dwWaitHint = 0;
DbgPrint(" [SLEEPY] sending install status #%d\n",i);
if (!SetServiceStatus (SleepyStatusHandle, &SleepyStatus)) { status = GetLastError(); DbgPrint(" [SLEEPY] SetServiceStatus error %ld\n",status); }
//
// Wait forever until we are told to terminate.
//
status = WaitForSingleObject ( SleepyDoneEvent, INFINITE_WAIT_TIME);
DbgPrint(" [SLEEPY] Leaving the Sleepy service\n");
CloseHandle(SleepyDoneEvent); return(NO_ERROR); }
/****************************************************************************/ VOID SleepyCtrlHandler ( IN DWORD Opcode ) {
DWORD status;
DbgPrint(" [SLEEPY] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE:
SleepyStatus.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE:
SleepyStatus.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_STOP:
SleepyStatus.dwWin32ExitCode = 0; SleepyStatus.dwCheckPoint = 0; SleepyStatus.dwWaitHint = 0; SleepyStatus.dwCurrentState = SERVICE_STOPPED;
SetEvent(SleepyDoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: break;
default: DbgPrint(" [SLEEPY] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (SleepyStatusHandle, &SleepyStatus)) { status = GetLastError(); DbgPrint(" [SLEEPY] SetServiceStatus error %ld\n",status); } return; }
/****************************************************************************/ DWORD DeadStart ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i;
DbgPrint(" [DEAD] Inside the Dead Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [DEAD] CommandArg%d = %s\n", i,argv[i]); }
DeadDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
DeadStatus.dwServiceType = SERVICE_WIN32; DeadStatus.dwCurrentState = SERVICE_STOPPED; DeadStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; DeadStatus.dwWin32ExitCode = 0x00020002; DeadStatus.dwServiceSpecificExitCode = 0; DeadStatus.dwCheckPoint = 0; DeadStatus.dwWaitHint = 0;
//
// Register the Control Handler routine.
//
DbgPrint(" [DEAD] Getting Ready to call RegisterServiceCtrlHandler\n");
DeadStatusHandle = RegisterServiceCtrlHandler( TEXT("dead"), DeadCtrlHandler);
if (DeadStatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [DEAD] RegisterServiceCtrlHandler failed %d\n", GetLastError()); }
//
// The Dead Service will now exit process prior to sending its first
// status.
//
DbgPrint(" [DEAD] Terminating the Dead Service Process\n"); ExitProcess(0);
//
// Return the status
//
if (!SetServiceStatus (DeadStatusHandle, &DeadStatus)) { status = GetLastError(); DbgPrint(" [DEAD] SetServiceStatus error %ld\n",status); }
//
// Wait forever until we are told to terminate.
//
status = WaitForSingleObject ( DeadDoneEvent, INFINITE_WAIT_TIME);
DbgPrint(" [DEAD] Leaving the dead service\n");
CloseHandle(DeadDoneEvent); return(NO_ERROR); }
/****************************************************************************/ VOID DeadCtrlHandler ( IN DWORD Opcode ) {
DWORD status;
DbgPrint(" [DEAD] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE:
DeadStatus.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE:
DeadStatus.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_STOP:
DeadStatus.dwWin32ExitCode = 0; DeadStatus.dwCurrentState = SERVICE_STOPPED;
SetEvent(DeadDoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: break;
default: DbgPrint(" [DEAD] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (DeadStatusHandle, &DeadStatus)) { status = GetLastError(); DbgPrint(" [DEAD] SetServiceStatus error %ld\n",status); } return; }
/****************************************************************************/
//
// SlowStop will take a long time to stop.
//
//
DWORD SlowStopStart ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i; DWORD LoopCount;
DbgPrint(" [SLOW_STOP] Inside the SlowStop Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [SLOW_STOP] CommandArg%d = %s\n", i,argv[i]); }
SlowStopDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
SlowStopStatus.dwServiceType = SERVICE_WIN32; SlowStopStatus.dwCurrentState = SERVICE_RUNNING; SlowStopStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
SlowStopStatus.dwWin32ExitCode = 0; SlowStopStatus.dwServiceSpecificExitCode = 0; SlowStopStatus.dwCheckPoint = 0; SlowStopStatus.dwWaitHint = 0;
//
// Register the Control Handler routine.
//
DbgPrint(" [SLOW_STOP] Getting Ready to call RegisterServiceCtrlHandler\n");
SlowStopStatusHandle = RegisterServiceCtrlHandler( TEXT("slowstop"), SlowStopCtrlHandler);
if (SlowStopStatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [SLOW_STOP] RegisterServiceCtrlHandler failed %d\n", GetLastError()); }
//
// Return the status
//
if (!SetServiceStatus (SlowStopStatusHandle, &SlowStopStatus)) { status = GetLastError(); DbgPrint(" [SLOW_STOP] SetServiceStatus error %ld\n",status); }
//
// Put up a message box to get information on how long it should take
// this service to stop. The choices are to stop within the WaitHint
// time period - and to stop outside of the WaitHint time period
//
//
// Ask the user how long to take in stopping
//
status = MessageBox( NULL, "Press YES Stop occurs within WaitHint Period\n" "Press NO Stop takes longer than the WaitHint Period\n" "Press CANCEL Stop occurs within WaitHint Period", "SlowStopStart", MB_YESNOCANCEL | MB_SERVICE_NOTIFICATION);
DbgPrint("MessageBox return status = %d\n",status); SvcPrintf("I got the status\n"); switch(status){ case IDNO: LoopCount = 30; break; case IDYES: LoopCount = 6; break; case IDCANCEL: LoopCount = 6; break; }
//
// Wait forever until we are told to terminate.
//
status = WaitForSingleObject ( SlowStopDoneEvent, INFINITE_WAIT_TIME);
//===============================================
//
// When shutting down, send the STOP_PENDING
// status for 8 seconds then STOP.
// The WaitHint indicates it takes 10 seconds
// to stop.
//
//===============================================
for (i=0; i<LoopCount ; i++ ) {
Sleep(1000);
SlowStopStatus.dwCheckPoint++;
if (!SetServiceStatus (SlowStopStatusHandle, &SlowStopStatus)) { status = GetLastError(); DbgPrint(" [SLOW_STOP] SetServiceStatus error %ld\n",status); }
}
SlowStopStatus.dwCurrentState = SERVICE_STOPPED; SlowStopStatus.dwCheckPoint=0; SlowStopStatus.dwWaitHint=0;
if (!SetServiceStatus (SlowStopStatusHandle, &SlowStopStatus)) { status = GetLastError(); DbgPrint(" [SLOW_STOP] SetServiceStatus error %ld\n",status); }
DbgPrint(" [SLOW_STOP] Leaving the slowstop service\n");
CloseHandle(SlowStopDoneEvent); return(NO_ERROR); }
/****************************************************************************/ VOID SlowStopCtrlHandler ( IN DWORD Opcode ) {
DWORD status;
DbgPrint(" [SLOW_STOP] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE:
SlowStopStatus.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE:
SlowStopStatus.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN:
SlowStopStatus.dwWin32ExitCode = 0; SlowStopStatus.dwServiceSpecificExitCode = 0; SlowStopStatus.dwCurrentState = SERVICE_STOP_PENDING; SlowStopStatus.dwWaitHint = 10000; // 10 seconds to stop
// SlowStopStatus.dwWaitHint = 0; // 10 seconds to stop
SlowStopStatus.dwCheckPoint = 1;
SetEvent(SlowStopDoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: break;
default: DbgPrint(" [SLOW_STOP] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (SlowStopStatusHandle, &SlowStopStatus)) { status = GetLastError(); DbgPrint(" [SLOW_STOP] SetServiceStatus error %ld\n",status); } return; }
/****************************************************************************/
//
// Terminate will die unexpectedly.
//
//
DWORD TerminateStart ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i;
DbgPrint(" [TERMINATE] Inside the Terminate Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [TERMINATE] CommandArg%d = %s\n", i,argv[i]); }
TerminateDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
TerminateStatus.dwServiceType = SERVICE_WIN32; TerminateStatus.dwCurrentState = SERVICE_RUNNING; TerminateStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
TerminateStatus.dwWin32ExitCode = 0; TerminateStatus.dwServiceSpecificExitCode = 0; TerminateStatus.dwCheckPoint = 0; TerminateStatus.dwWaitHint = 0; //
// Register the Control Handler routine.
//
DbgPrint(" [TERMINATE] Getting Ready to call RegisterServiceCtrlHandler\n");
TerminateStatusHandle = RegisterServiceCtrlHandler( TEXT("terminate"), TerminateCtrlHandler);
if (TerminateStatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [TERMINATE] RegisterServiceCtrlHandler failed %d\n", GetLastError()); }
//
// Return the status
//
if (!SetServiceStatus (TerminateStatusHandle, &TerminateStatus)) { status = GetLastError(); DbgPrint(" [TERMINATE] SetServiceStatus error %ld\n",status); }
//=======================================================================
//
// Sleep for 20 seconds, then send out an error status, and ExitProcess.
// NOTE: It would be more proper for a service to ExitThread here
// instead. But who says test services need to be proper?
//
//=======================================================================
Sleep(20000);
TerminateStatus.dwCurrentState = SERVICE_STOPPED; TerminateStatus.dwWin32ExitCode = ERROR_INVALID_ENVIRONMENT; TerminateStatus.dwCheckPoint=0; TerminateStatus.dwWaitHint=0;
if (!SetServiceStatus (TerminateStatusHandle, &TerminateStatus)) { status = GetLastError(); DbgPrint(" [TERMINATE] SetServiceStatus error %ld\n",status); }
ExitProcess(NO_ERROR); return(NO_ERROR);
}
/****************************************************************************/ VOID TerminateCtrlHandler ( IN DWORD Opcode ) {
DWORD status;
DbgPrint(" [TERMINATE] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE:
TerminateStatus.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE:
TerminateStatus.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_STOP:
TerminateStatus.dwWin32ExitCode = 0; TerminateStatus.dwServiceSpecificExitCode = 0; TerminateStatus.dwCurrentState = SERVICE_STOP_PENDING; TerminateStatus.dwCheckPoint = 1; TerminateStatus.dwWaitHint = 20000;
SetEvent(TerminateDoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: break;
default: DbgPrint(" [TERMINATE] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (TerminateStatusHandle, &TerminateStatus)) { status = GetLastError(); DbgPrint(" [TERMINATE] SetServiceStatus error %ld\n",status); }
CloseHandle(TerminateDoneEvent); return; }
/****************************************************************************/
//
// Bad1 will never call RegisterServiceCtrlHandler.
//
//
DWORD Bad1Start ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i;
DbgPrint(" [BAD1] Inside the Bad1 Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [BAD1] CommandArg%d = %s\n", i,argv[i]); }
Bad1DoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
Bad1Status.dwServiceType = SERVICE_WIN32; Bad1Status.dwCurrentState = SERVICE_START_PENDING; Bad1Status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
Bad1Status.dwWin32ExitCode = 0; Bad1Status.dwServiceSpecificExitCode = 0; Bad1Status.dwCheckPoint = 1; Bad1Status.dwWaitHint = 5000; //
// Register the Control Handler routine.
//
/////////////////////////////////
// Sleep for a real long time
// without calling RegisterServiceCtrlHandler.
DbgPrint(" [BAD1] Getting Ready to sleep\n"); Sleep(9999999);
////////////////////////////////////////////////
//
//
// Wait forever until we are told to terminate.
//
status = WaitForSingleObject ( Bad1DoneEvent, INFINITE_WAIT_TIME);
DbgPrint(" [BAD1] Leaving the Bad1 service\n"); CloseHandle(Bad1DoneEvent); return(NO_ERROR); }
/****************************************************************************/ VOID Bad1CtrlHandler ( IN DWORD Opcode ) {
DWORD status;
DbgPrint(" [BAD1] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE:
Bad1Status.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE:
Bad1Status.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_STOP:
Bad1Status.dwWin32ExitCode = 0; Bad1Status.dwServiceSpecificExitCode = 0; Bad1Status.dwCurrentState = SERVICE_STOP_PENDING; Bad1Status.dwCheckPoint = 1; Bad1Status.dwWaitHint = 20000;
SetEvent(Bad1DoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: break;
default: DbgPrint(" [BAD1] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (Bad1StatusHandle, &Bad1Status)) { status = GetLastError(); DbgPrint(" [BAD1] SetServiceStatus error %ld\n",status); }
CloseHandle(Bad1DoneEvent); return; }
/****************************************************************************/
//
// Bad2 will never complete initialization (stuck in START_PENDING forever).
// The control handler is functioning and STOP is functioning.
//
//
DWORD Bad2Start ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i;
DbgPrint(" [BAD2] Inside the Bad2 Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [BAD2] CommandArg%d = %s\n", i,argv[i]); }
Bad2DoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
Bad2Status.dwServiceType = SERVICE_WIN32; Bad2Status.dwCurrentState = SERVICE_START_PENDING; Bad2Status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
Bad2Status.dwWin32ExitCode = 0; Bad2Status.dwServiceSpecificExitCode = 0; Bad2Status.dwCheckPoint = 1; Bad2Status.dwWaitHint = 5000; //
// Register the Control Handler routine.
//
DbgPrint(" [BAD2] Getting Ready to call RegisterServiceCtrlHandler\n");
Bad2StatusHandle = RegisterServiceCtrlHandler( TEXT("Bad2"), Bad2CtrlHandler);
if (Bad2StatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [BAD2] RegisterServiceCtrlHandler failed %d\n", GetLastError()); }
//
// Return the status
//
if (!SetServiceStatus (Bad2StatusHandle, &Bad2Status)) { status = GetLastError(); DbgPrint(" [BAD2] SetServiceStatus error %ld\n",status); } #ifdef remove
/////////////////////////////////
// Sleep for a real long time
// without sending status.
DbgPrint(" [BAD2] Getting Ready to sleep\n"); Sleep(9999999); #endif
/////////////////////////////////
//
// Wait forever until we are told to terminate.
//
status = WaitForSingleObject ( Bad2DoneEvent, INFINITE_WAIT_TIME);
DbgPrint(" [BAD2] Leaving the Bad2 service\n"); CloseHandle(Bad2DoneEvent); return(NO_ERROR);
}
/****************************************************************************/ VOID Bad2CtrlHandler ( IN DWORD Opcode ) {
DWORD status;
DbgPrint(" [BAD2] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE:
Bad2Status.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE:
Bad2Status.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_STOP:
Bad2Status.dwWin32ExitCode = 0; Bad2Status.dwServiceSpecificExitCode = 0; Bad2Status.dwCurrentState = SERVICE_STOPPED; Bad2Status.dwCheckPoint = 1; Bad2Status.dwWaitHint = 5000;
SetEvent(Bad2DoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: break;
default: DbgPrint(" [BAD2] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (Bad2StatusHandle, &Bad2Status)) { status = GetLastError(); DbgPrint(" [BAD2] SetServiceStatus error %ld\n",status); }
CloseHandle(Bad2DoneEvent); return; }
/****************************************************************************/ //
// Bad3 will send only its first START_PENDING status, and then it won't send
// any further status messages for any reason. Aside from not sending any
// status messages, the service operates normally.
//
DWORD Bad3Start ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i;
DbgPrint(" [BAD3] Inside the Bad3 Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [BAD3] CommandArg%d = %s\n", i,argv[i]); }
Bad3DoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
Bad3Status.dwServiceType = SERVICE_WIN32; Bad3Status.dwCurrentState = SERVICE_START_PENDING; Bad3Status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
Bad3Status.dwWin32ExitCode = 0; Bad3Status.dwServiceSpecificExitCode = 0; Bad3Status.dwCheckPoint = 1; Bad3Status.dwWaitHint = 5000; //
// Register the Control Handler routine.
//
DbgPrint(" [BAD3] Getting Ready to call RegisterServiceCtrlHandler\n");
Bad3StatusHandle = RegisterServiceCtrlHandler( TEXT("Bad3"), Bad3CtrlHandler);
if (Bad3StatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [BAD3] RegisterServiceCtrlHandler failed %d\n", GetLastError()); }
//
// Return the status
//
if (!SetServiceStatus (Bad3StatusHandle, &Bad3Status)) { status = GetLastError(); DbgPrint(" [BAD3] SetServiceStatus error %ld\n",status); }
//
// Wait forever until we are told to terminate.
//
status = WaitForSingleObject ( Bad3DoneEvent, INFINITE_WAIT_TIME);
DbgPrint(" [BAD3] Leaving the Bad3 service\n"); CloseHandle(Bad3DoneEvent); return(NO_ERROR);
}
/****************************************************************************/ VOID Bad3CtrlHandler ( IN DWORD Opcode ) { DbgPrint(" [BAD3] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE:
Bad3Status.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE:
Bad3Status.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_STOP:
Bad3Status.dwWin32ExitCode = 0; Bad3Status.dwServiceSpecificExitCode = 0; Bad3Status.dwCurrentState = SERVICE_STOPPED; Bad3Status.dwCheckPoint = 1; Bad3Status.dwWaitHint = 20000;
SetEvent(Bad3DoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: break;
default: DbgPrint(" [BAD3] Unrecognized opcode %ld\n", Opcode); }
//
// Don't send a status response.
//
#ifdef REMOVE
if (!SetServiceStatus (Bad3StatusHandle, &Bad3Status)) { status = GetLastError(); DbgPrint(" [BAD3] SetServiceStatus error %ld\n",status); } #endif
CloseHandle(Bad3DoneEvent); return; }
/****************************************************************************/
//
// Bad4 will start normally, but on stop it only sends one stop pending
// status before it terminates itself without further notification.
//
DWORD Bad4Start ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i;
DbgPrint(" [BAD4] Inside the Bad4 Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [BAD4] CommandArg%d = %s\n", i,argv[i]); }
Bad4DoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
Bad4Status.dwServiceType = SERVICE_WIN32; Bad4Status.dwCurrentState = SERVICE_RUNNING; Bad4Status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
Bad4Status.dwWin32ExitCode = 0; Bad4Status.dwServiceSpecificExitCode = 0; Bad4Status.dwCheckPoint = 0; Bad4Status.dwWaitHint = 0;
//
// Register the Control Handler routine.
//
DbgPrint(" [BAD4] Getting Ready to call RegisterServiceCtrlHandler\n");
Bad4StatusHandle = RegisterServiceCtrlHandler( TEXT("Bad4"), Bad4CtrlHandler);
if (Bad4StatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [BAD4] RegisterServiceCtrlHandler failed %d\n", GetLastError()); }
//
// Return the status
//
if (!SetServiceStatus (Bad4StatusHandle, &Bad4Status)) { status = GetLastError(); DbgPrint(" [BAD4] SetServiceStatus error %ld\n",status); }
//
// Wait forever until we are told to terminate.
//
status = WaitForSingleObject ( Bad4DoneEvent, INFINITE_WAIT_TIME);
DbgPrint(" [BAD4] Leaving the Bad4 service\n"); CloseHandle(Bad4DoneEvent); return(NO_ERROR); }
/****************************************************************************/ VOID Bad4CtrlHandler ( IN DWORD Opcode ) {
DWORD status;
DbgPrint(" [BAD4] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE:
Bad4Status.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE:
Bad4Status.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_STOP:
Bad4Status.dwWin32ExitCode = 0; Bad4Status.dwServiceSpecificExitCode = 0; Bad4Status.dwCurrentState = SERVICE_STOP_PENDING; Bad4Status.dwCheckPoint = 1; Bad4Status.dwWaitHint = 20000;
SetEvent(Bad4DoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: break;
default: DbgPrint(" [BAD4] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (Bad4StatusHandle, &Bad4Status)) { status = GetLastError(); DbgPrint(" [BAD4] SetServiceStatus error %ld\n",status); }
CloseHandle(Bad4DoneEvent); return; }
/****************************************************************************/
//
// HangOnStop Service doesn't return from the control handling routine
// on STOP requests until after the pipe timeout period (30 seconds).
// After 40 seconds, it sends a STOP_PENDING status.
//
// Just to confuse things, after the timeout, this service sends a
// RUNNING status (after an additional 30msec delay). Then it sleeps for
// 20 seconds before sending a STOPPED status.
//
DWORD HangOnStopStart ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i;
DbgPrint(" [HangOnStop] Inside the HangOnStop Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [HangOnStop] CommandArg%d = %s\n", i,argv[i]); }
HangOnStopDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
HangOnStopStatus.dwServiceType = SERVICE_WIN32; HangOnStopStatus.dwCurrentState = SERVICE_RUNNING; HangOnStopStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
HangOnStopStatus.dwWin32ExitCode = 0; HangOnStopStatus.dwServiceSpecificExitCode = 0; HangOnStopStatus.dwCheckPoint = 0; HangOnStopStatus.dwWaitHint = 0;
//
// Register the Control Handler routine.
//
DbgPrint(" [HangOnStop] Getting Ready to call RegisterServiceCtrlHandler\n");
HangOnStopStatusHandle = RegisterServiceCtrlHandler( TEXT("HangOnStop"), HangOnStopCtrlHandler);
if (HangOnStopStatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [HangOnStop] RegisterServiceCtrlHandler failed %d\n", GetLastError()); }
//
// Return the status
//
if (!SetServiceStatus (HangOnStopStatusHandle, &HangOnStopStatus)) { status = GetLastError(); DbgPrint(" [HangOnStop] SetServiceStatus error %ld\n",status); }
//
// Wait forever until we are told to terminate.
//
status = WaitForSingleObject ( HangOnStopDoneEvent, INFINITE_WAIT_TIME);
Sleep(30);
HangOnStopStatus.dwCurrentState = SERVICE_RUNNING; if (!SetServiceStatus (HangOnStopStatusHandle, &HangOnStopStatus)) { status = GetLastError(); DbgPrint(" [HangOnStop] SetServiceStatus error %ld\n",status); }
Sleep(20000);
HangOnStopStatus.dwCurrentState = SERVICE_STOPPED; if (!SetServiceStatus (HangOnStopStatusHandle, &HangOnStopStatus)) { status = GetLastError(); DbgPrint(" [HangOnStop] SetServiceStatus error %ld\n",status); }
DbgPrint(" [HangOnStop] Leaving the HangOnStop service\n"); CloseHandle(HangOnStopDoneEvent); return(NO_ERROR); }
/****************************************************************************/ VOID HangOnStopCtrlHandler ( IN DWORD Opcode ) {
DWORD status;
DbgPrint(" [HangOnStop] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE:
HangOnStopStatus.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE:
HangOnStopStatus.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_STOP:
HangOnStopStatus.dwWin32ExitCode = 0; HangOnStopStatus.dwServiceSpecificExitCode = 0; HangOnStopStatus.dwCurrentState = SERVICE_STOP_PENDING; HangOnStopStatus.dwCheckPoint = 1; HangOnStopStatus.dwWaitHint = 20000;
Sleep(40000);
SetEvent(HangOnStopDoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: break;
default: DbgPrint(" [HangOnStop] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (HangOnStopStatusHandle, &HangOnStopStatus)) { status = GetLastError(); DbgPrint(" [HangOnStop] SetServiceStatus error %ld\n",status); }
CloseHandle(HangOnStopDoneEvent); return; }
/****************************************************************************/ DWORD StartProcStart ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i; STARTUPINFOW ScStartupInfo; PROCESS_INFORMATION processInfo; LPWSTR ImageName; HWND hWnd= NULL;
DbgPrint(" [START_PROC] Inside the StartProc Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [START_PROC] CommandArg%d = %s\n", i,argv[i]); }
//
// This call to a GDI function causes a connection to the Win
// User Server. It doesn't matter which GDI function is called, this
// one happens to be easiest. This allows us to create a child process
// that is interactive with the user (like cmd.exe).
//
hWnd = GetDesktopWindow(); if (hWnd == NULL) { DbgPrint(" [START_PROC] GetDesktopWindow call failed %d\n", GetLastError()); }
//
// Create an event to wait on.
//
StartProcDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
StartProcStatus.dwServiceType = SERVICE_WIN32; StartProcStatus.dwCurrentState = SERVICE_RUNNING; StartProcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN; StartProcStatus.dwWin32ExitCode = 0; StartProcStatus.dwServiceSpecificExitCode = 0; StartProcStatus.dwCheckPoint = 0; StartProcStatus.dwWaitHint = 0;
//
// Register the Control Handler routine.
//
DbgPrint(" [START_PROC] Getting Ready to call RegisterServiceCtrlHandler\n");
StartProcStatusHandle = RegisterServiceCtrlHandler( TEXT("StartProc"), StartProcCtrlHandler);
if (StartProcStatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [START_PROC] RegisterServiceCtrlHandler failed %d\n", GetLastError()); }
//
// Return the status
//
if (!SetServiceStatus (StartProcStatusHandle, &StartProcStatus)) { status = GetLastError(); DbgPrint(" [START_PROC] SetServiceStatus error %ld\n",status); }
//*******************************************************************
// Start a Child Process
//
ScStartupInfo.cb = sizeof(STARTUPINFOW); // size
ScStartupInfo.lpReserved = NULL; // lpReserved
ScStartupInfo.lpDesktop = NULL; // DeskTop
ScStartupInfo.lpTitle = L"Local System Window"; // Title
ScStartupInfo.dwX = 0; // X (position)
ScStartupInfo.dwY = 0; // Y (position)
ScStartupInfo.dwXSize = 0; // XSize (dimension)
ScStartupInfo.dwYSize = 0; // YSize (dimension)
ScStartupInfo.dwXCountChars = 0; // XCountChars
ScStartupInfo.dwYCountChars = 0; // YCountChars
ScStartupInfo.dwFillAttribute = 0; // FillAttributes
ScStartupInfo.dwFlags = STARTF_FORCEOFFFEEDBACK; // Flags - should be STARTF_TASKNOTCLOSABLE
ScStartupInfo.wShowWindow = SW_SHOWNORMAL; // ShowWindow
ScStartupInfo.cbReserved2 = 0L; // cbReserved
ScStartupInfo.lpReserved2 = NULL; // lpReserved
// ScStartupInfo.dwFlags |= STARTF_DESKTOPINHERIT;
// ScStartupInfo.lpDesktop = pszInteractiveDesktop;
ImageName = L"cmd.exe";
if (!CreateProcessW ( NULL, // Fully qualified image name
ImageName, // Command Line
NULL, // Process Attributes
NULL, // Thread Attributes
TRUE, // Inherit Handles
CREATE_NEW_CONSOLE, // Creation Flags
NULL, // Pointer to Environment block
NULL, // Pointer to Current Directory
&ScStartupInfo, // Startup Info
&processInfo) // ProcessInformation
) {
status = GetLastError(); DbgPrint(" [START_PROC] CreateProcess %ws failed %d \n", ImageName, status); } else { DbgPrint(" [START_PROC]CreateProcess Success \n"); }
//
//
//*******************************************************************
//
// Wait forever until we are told to terminate.
//
status = WaitForSingleObject ( StartProcDoneEvent, INFINITE_WAIT_TIME);
DbgPrint(" [START_PROC] Leaving the StartProc service\n");
CloseHandle(StartProcDoneEvent); CloseHandle(hWnd); return(NO_ERROR); }
/****************************************************************************/ VOID StartProcCtrlHandler ( IN DWORD Opcode ) {
DWORD status;
DbgPrint(" [START_PROC] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE:
StartProcStatus.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE:
StartProcStatus.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_STOP:
StartProcStatus.dwWin32ExitCode = 0; StartProcStatus.dwCurrentState = SERVICE_STOPPED;
SetEvent(StartProcDoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: break;
default: DbgPrint(" [START_PROC] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (StartProcStatusHandle, &StartProcStatus)) { status = GetLastError(); DbgPrint(" [START_PROC] SetServiceStatus error %ld\n",status); } return; }
/****************************************************************************/ DWORD StartAndDieStart ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i; DWORD checkpoint=1;
DbgPrint(" [StartAndDie] Inside the StartAndDie Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [START&DIE] CommandArg%d = %s\n", i,argv[i]); }
StartAndDieDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
StartAndDieStatus.dwServiceType = SERVICE_WIN32; StartAndDieStatus.dwCurrentState = SERVICE_START_PENDING; StartAndDieStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN; StartAndDieStatus.dwWin32ExitCode = 0; StartAndDieStatus.dwServiceSpecificExitCode = 0; StartAndDieStatus.dwCheckPoint = checkpoint++; StartAndDieStatus.dwWaitHint = 40000;
//
// Register the Control Handler routine.
//
DbgPrint(" [START&DIE] Getting Ready to call RegisterServiceCtrlHandler\n");
StartAndDieStatusHandle = RegisterServiceCtrlHandler( TEXT("StartAndDie"), StartAndDieCtrlHandler);
if (StartAndDieStatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [START&DIE] RegisterServiceCtrlHandler failed %d\n", GetLastError()); }
//
// Return the status
//
if (!SetServiceStatus (StartAndDieStatusHandle, &StartAndDieStatus)) { status = GetLastError(); DbgPrint(" [START&DIE] SetServiceStatus error %ld\n",status); }
//
// Sleep for a bit, the say we are running, then say we are stopped.
//
Sleep(30000);
StartAndDieStatus.dwCurrentState = SERVICE_RUNNING; StartAndDieStatus.dwCheckPoint = 0; StartAndDieStatus.dwWaitHint = 0;
if (!SetServiceStatus (StartAndDieStatusHandle, &StartAndDieStatus)) { status = GetLastError(); DbgPrint("[START&DIE] SetServiceStatus error %ld\n",status); }
StartAndDieStatus.dwCurrentState = SERVICE_STOPPED; StartAndDieStatus.dwCheckPoint = 0; StartAndDieStatus.dwWaitHint = 0; StartAndDieStatus.dwWin32ExitCode = ERROR_INVALID_ENVIRONMENT;
if (!SetServiceStatus (StartAndDieStatusHandle, &StartAndDieStatus)) { status = GetLastError(); DbgPrint("[START&DIE] SetServiceStatus error %ld\n",status); }
DbgPrint(" [START&DIE] Leaving the start&die service\n");
CloseHandle(StartAndDieDoneEvent); return(NO_ERROR); }
/****************************************************************************/ VOID StartAndDieCtrlHandler ( IN DWORD Opcode ) {
DWORD status;
DbgPrint(" [START&DIE] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE: SvcPrintf("StartAndDie received a PAUSE\n"); StartAndDieStatus.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE: SvcPrintf("StartAndDie received a CONTINUE\n"); StartAndDieStatus.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_STOP: SvcPrintf("StartAndDie received a STOP\n");
StartAndDieStatus.dwWin32ExitCode = 0; StartAndDieStatus.dwCurrentState = SERVICE_STOPPED;
SetEvent(StartAndDieDoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: SvcPrintf("StartAndDie received an INTERROGATE\n"); break;
default: DbgPrint(" [START&DIE] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (StartAndDieStatusHandle, &StartAndDieStatus)) { status = GetLastError(); DbgPrint(" [START&DIE] SetServiceStatus error %ld\n",status); } return; }
VOID SetUpConsole() {
//#ifdef NOT_NECESSARY
CONSOLE_SCREEN_BUFFER_INFO csbi; COORD coord; HANDLE consoleHandle=NULL;
if (!AllocConsole()) { DbgPrint("[TS2]AllocConsole failed %d\n",GetLastError()); }
consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); if (consoleHandle == NULL) { DbgPrint("[TS2]GetStdHandle failed %d\n",GetLastError()); }
if (!GetConsoleScreenBufferInfo( GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { DbgPrint("[TS2]GetConsoleScreenBufferInfo failed %d\n",GetLastError()); } coord.X = (SHORT)(csbi.srWindow.Right - csbi.srWindow.Left + 1); coord.Y = (SHORT)((csbi.srWindow.Bottom - csbi.srWindow.Top + 1) * 20); if (!SetConsoleScreenBufferSize( GetStdHandle(STD_OUTPUT_HANDLE), coord)) {
DbgPrint("[TS2]SetConsoleScreenBufferSize failed %d\n",GetLastError()); }
//#endif //NOT_NECESSARY
DbgLogFileHandle = CreateFile("\\trace.log", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); }
VOID SvcPrintf ( char *Format, ... )
/*++
Routine Description:
This routine provides printf functionality when the service is run with REMOTE.EXE.
sc config LUMPY binpath= "remote /s \"ts2\" LUMPY"
NOTE: It is not necessary to allocate a console in this case because remote already provides one. So the only portion of SetupConsole() that is used is the portion the opens the debug dump file.
Arguments:
Same as printf
Return Value:
--*/ { va_list arglist; char OutputBuffer[1024]; ULONG length;
va_start( arglist, Format );
vsprintf( OutputBuffer, Format, arglist );
va_end( arglist );
length = strlen( OutputBuffer );
if (!WriteFile( GetStdHandle(STD_OUTPUT_HANDLE), (LPVOID )OutputBuffer, length, &length, NULL )) {
DbgPrint("[TS2]WriteFile Failed %d \n",GetLastError()); }
if(DbgLogFileHandle != INVALID_HANDLE_VALUE) {
if (!WriteFile( DbgLogFileHandle, (LPVOID )OutputBuffer, length, &length, NULL )) {
DbgPrint("[TS2]WriteFile Failed %d \n",GetLastError()); } }
} // SsPrintf
|