Shane G. Brodie
2003-11-26 19:45:15 UTC
Hello all:
Having problems writing a fairly simple Windows Service. The install
procedure seems to work well. After install, when
StartServiceCtrlDispatcher is called, everything blows chunks with
meaningful(sic) error 1063. Source code follows:
Have pity on me ... my C/C++ is extremely rusty.
Regards
Shane Brodie
//***************************************************
//console main function used to register/install/uninstall service
int main(int argc, char *argv[] )
{
if (argc > 1)
{
//If we want to install ...
if (strcmp(argv[1],"-i") == 0 || strcmp(argv[1],"-I") == 0)
{
if(InstallService() == TRUE)
{
SERVICE_TABLE_ENTRY DispatchTable[] = {
{ "DZSvc", (LPSERVICE_MAIN_FUNCTION) ServiceMain },
{ NULL, NULL }};
if (StartServiceCtrlDispatcher(DispatchTable) == 0)
{
//here is where the error appears. ServiceMain and InstallService functions
follow below
printf("StartServiceCtrlDispatcher error = %d\n", GetLastError());
}
else
{
printf("File Relay Service Installed Sucessfully\n");
}
}
else
{
printf("File Relay Service installation failed error = %d\n",
GetLastError());
}
}
//if we want to remove ...
if (strcmp(argv[1],"-u") ==0 || strcmp(argv[1],"-U") == 0)
{
if (DeleteService() == TRUE)
{
//Send message to event log
printf("File Relay Service UnInstalled Sucessfully\n");
}
else
{
//Send message to event log
printf("Error Uninstalling File Relay Service\n");
}
}
if (!strcmp(argv[1],"i") && !strcmp(argv[1],"I") && !strcmp(argv[1],"u")
&& !strcmp(argv[1],"U"))
{
printf("\n\nUnknown Switch Usage - %s\n\nFor Install use DZSvc -i\n\nFor
UnInstall use DPSvc -u\n", argv[1]);
}
}
return 0;
}
//***************************************************
//ServiceMain - used to start the service during execution
VOID ServiceMain (DWORD argc, LPTSTR *argv)
{
DWORD status;
DWORD specificError;
BOOL bSuccess;
__int64 qwDueTime;
LARGE_INTEGER liDueTime;
// ... snipped ...
ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_PAUSE_CONTINUE;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 1000;
ServiceStatusHandle = RegisterServiceCtrlHandler( "DZSvc",
(LPHANDLER_FUNCTION)ServiceCtrlHandler);
if (ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
printf("DZSvc RegisterServiceCtrlHandler failed %d\n",
GetLastError());
return;
}
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
//create a waitable timer
if ( hTimer = CreateWaitableTimer(
NULL, // Default security attributes.
FALSE, // Create auto-reset timer.
"DZSvcTimer" ) ) // Name of waitable timer.
{
ServiceStatus.dwCheckPoint = 1;
ServiceStatus.dwWaitHint = 1000;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
__try
{
// Create a negative 64-bit integer that will be used to
// signal the timer for the first time, 5 seconds from now.
qwDueTime = -5 * _SECOND;
// Copy the relative time into a LARGE_INTEGER.
liDueTime.LowPart = (DWORD) ( qwDueTime & 0xFFFFFFFF );
liDueTime.HighPart = (LONG) ( qwDueTime >> 32 );
//set the timer to go off once every hour
bSuccess = SetWaitableTimer(
hTimer, // Handle to the timer object.
&liDueTime, // When timer will become signaled.
5000, // Periodic timer interval of once every 15 minutes
(PTIMERAPCROUTINE)CheckDropZone, // Completion routine.
NULL, // Argument to the completion routine.
FALSE ); // Do not restore a suspended system.
//if we were successful in setting the time, go to sleep
if ( bSuccess )
{
//If we make it to here, all is well ...
// The timer is set
// Lets update our service state and wait it out
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
// LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_STARTED, NULL,NULL,NULL);
}
else
{
//otherwise ... generate a failure message to the Event Log
// LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_FAILEDINIT, NULL,NULL,NULL);
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
return;
}
}
__finally
{
//If we blow chunks in the Try block ... clean-up
CloseHandle( hTimer );
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
return;
}
} else {
//We couldn't create a waitable timer ... let the event log know
// LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_FAILEDINIT, NULL,NULL,NULL);
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
return;
}
// Handle error condition
if (status != NO_ERROR)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
ServiceStatus.dwWin32ExitCode = status;
ServiceStatus.dwServiceSpecificExitCode = specificError;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
return;
}
// This is where the service does its work.
SleepEx(INFINITE, FALSE);
printf(" [DZSvc] Returning the Main Thread \n",0);
return;
}
//***************************************************
//Service installer routine
BOOL InstallService()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
LPCTSTR lpszDisplayName = "DZSvc";
char szEXEPath[1024];
schSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE,
SC_MANAGER_ALL_ACCESS);
if (!schSCManager)
{
return FALSE;
}
GetCurrentDirectory(1024,szEXEPath);
strcat(szEXEPath,"\\DZSvc.exe");
schService = CreateService(
schSCManager, // SCManager database
lpszDisplayName, // name of service
lpszDisplayName, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type - manual start
SERVICE_ERROR_NORMAL, // error control type
szEXEPath, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password
if (schService == NULL)
{
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return FALSE;
}
else
{
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return TRUE;
}
}
Having problems writing a fairly simple Windows Service. The install
procedure seems to work well. After install, when
StartServiceCtrlDispatcher is called, everything blows chunks with
meaningful(sic) error 1063. Source code follows:
Have pity on me ... my C/C++ is extremely rusty.
Regards
Shane Brodie
//***************************************************
//console main function used to register/install/uninstall service
int main(int argc, char *argv[] )
{
if (argc > 1)
{
//If we want to install ...
if (strcmp(argv[1],"-i") == 0 || strcmp(argv[1],"-I") == 0)
{
if(InstallService() == TRUE)
{
SERVICE_TABLE_ENTRY DispatchTable[] = {
{ "DZSvc", (LPSERVICE_MAIN_FUNCTION) ServiceMain },
{ NULL, NULL }};
if (StartServiceCtrlDispatcher(DispatchTable) == 0)
{
//here is where the error appears. ServiceMain and InstallService functions
follow below
printf("StartServiceCtrlDispatcher error = %d\n", GetLastError());
}
else
{
printf("File Relay Service Installed Sucessfully\n");
}
}
else
{
printf("File Relay Service installation failed error = %d\n",
GetLastError());
}
}
//if we want to remove ...
if (strcmp(argv[1],"-u") ==0 || strcmp(argv[1],"-U") == 0)
{
if (DeleteService() == TRUE)
{
//Send message to event log
printf("File Relay Service UnInstalled Sucessfully\n");
}
else
{
//Send message to event log
printf("Error Uninstalling File Relay Service\n");
}
}
if (!strcmp(argv[1],"i") && !strcmp(argv[1],"I") && !strcmp(argv[1],"u")
&& !strcmp(argv[1],"U"))
{
printf("\n\nUnknown Switch Usage - %s\n\nFor Install use DZSvc -i\n\nFor
UnInstall use DPSvc -u\n", argv[1]);
}
}
return 0;
}
//***************************************************
//ServiceMain - used to start the service during execution
VOID ServiceMain (DWORD argc, LPTSTR *argv)
{
DWORD status;
DWORD specificError;
BOOL bSuccess;
__int64 qwDueTime;
LARGE_INTEGER liDueTime;
// ... snipped ...
ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_PAUSE_CONTINUE;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 1000;
ServiceStatusHandle = RegisterServiceCtrlHandler( "DZSvc",
(LPHANDLER_FUNCTION)ServiceCtrlHandler);
if (ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
printf("DZSvc RegisterServiceCtrlHandler failed %d\n",
GetLastError());
return;
}
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
//create a waitable timer
if ( hTimer = CreateWaitableTimer(
NULL, // Default security attributes.
FALSE, // Create auto-reset timer.
"DZSvcTimer" ) ) // Name of waitable timer.
{
ServiceStatus.dwCheckPoint = 1;
ServiceStatus.dwWaitHint = 1000;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
__try
{
// Create a negative 64-bit integer that will be used to
// signal the timer for the first time, 5 seconds from now.
qwDueTime = -5 * _SECOND;
// Copy the relative time into a LARGE_INTEGER.
liDueTime.LowPart = (DWORD) ( qwDueTime & 0xFFFFFFFF );
liDueTime.HighPart = (LONG) ( qwDueTime >> 32 );
//set the timer to go off once every hour
bSuccess = SetWaitableTimer(
hTimer, // Handle to the timer object.
&liDueTime, // When timer will become signaled.
5000, // Periodic timer interval of once every 15 minutes
(PTIMERAPCROUTINE)CheckDropZone, // Completion routine.
NULL, // Argument to the completion routine.
FALSE ); // Do not restore a suspended system.
//if we were successful in setting the time, go to sleep
if ( bSuccess )
{
//If we make it to here, all is well ...
// The timer is set
// Lets update our service state and wait it out
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
// LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_STARTED, NULL,NULL,NULL);
}
else
{
//otherwise ... generate a failure message to the Event Log
// LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_FAILEDINIT, NULL,NULL,NULL);
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
return;
}
}
__finally
{
//If we blow chunks in the Try block ... clean-up
CloseHandle( hTimer );
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
return;
}
} else {
//We couldn't create a waitable timer ... let the event log know
// LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_FAILEDINIT, NULL,NULL,NULL);
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
return;
}
// Handle error condition
if (status != NO_ERROR)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
ServiceStatus.dwWin32ExitCode = status;
ServiceStatus.dwServiceSpecificExitCode = specificError;
SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
return;
}
// This is where the service does its work.
SleepEx(INFINITE, FALSE);
printf(" [DZSvc] Returning the Main Thread \n",0);
return;
}
//***************************************************
//Service installer routine
BOOL InstallService()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
LPCTSTR lpszDisplayName = "DZSvc";
char szEXEPath[1024];
schSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE,
SC_MANAGER_ALL_ACCESS);
if (!schSCManager)
{
return FALSE;
}
GetCurrentDirectory(1024,szEXEPath);
strcat(szEXEPath,"\\DZSvc.exe");
schService = CreateService(
schSCManager, // SCManager database
lpszDisplayName, // name of service
lpszDisplayName, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type - manual start
SERVICE_ERROR_NORMAL, // error control type
szEXEPath, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password
if (schService == NULL)
{
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return FALSE;
}
else
{
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return TRUE;
}
}