Discussion:
C/C++ Windows Service Neophyte - StartServiceCtrlDispatcher error = 1063
(too old to reply)
Shane G. Brodie
2003-11-26 19:45:15 UTC
Permalink
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;
}

}
Steve Fallows
2003-11-26 23:57:45 UTC
Permalink
If I understand your code correctly you are running it as a regular app,
having it do the install and then expecting it to continue on running as a
service?
If I'm wrong ignore the rest.

It doesn't work that way. After running the install, the app should exit.
The use the
Control Panel applet or "net start <service name> to start it.

I don't think you can use printf to debug anything - service have no
console.
You can use message boxes if you add SERVICE_INTERACTIVE_PROCESS
to the ServiceStatus.dwServiceType

HTH,
Steve
Post by Shane G. Brodie
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
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
Post by Shane G. Brodie
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;
}
}
Shane Brodie
2003-11-27 04:42:50 UTC
Permalink
Post by Steve Fallows
If I understand your code correctly you are running it as a regular app,
having it do the install and then expecting it to continue on running as a
service?
If I'm wrong ignore the rest.
Nope, after the install, I expect to launch the service either using Control
Panel or Net Start <service name> or custom controller application ... etc.
Post by Steve Fallows
It doesn't work that way. After running the install, the app should exit.
The use the
Control Panel applet or "net start <service name> to start it.
I don't think you can use printf to debug anything - service have no
console.
You can use message boxes if you add SERVICE_INTERACTIVE_PROCESS
to the ServiceStatus.dwServiceType
The printf stuff is only in the main() and InstallService() procedures which
are used only for installation and registration of the service. The
completed service is supposed to handle moving files within a network, and
will a specific user or require admin level access. In those cases you
cannot use SERVICE_INTERACTIVE_PROCESS
as this will only work under a local system account AFAIK.

The problem is the the line:

StartServiceCtrlDispatcher(DispatchTable) == 0

Is generating error 1063(??? I think ... the source at in the office). I'm
trying to figure why this is occurring. Even removing all printf statements
doesn't resolve the problem.

Thanks Again

Shane
Steve Fallows
2003-11-27 15:09:59 UTC
Permalink
Well, obviously you're less of a neophyte than I thought at first :)

1063 means "The service process could not connect to the service
controller." Possibly some kind
of user/account/security problem??

Sorry I can't be of more help. I've written one service and never hit this
problem.

Steve
Roy Fine
2003-11-27 17:06:05 UTC
Permalink
Shane,

The basic rule for the service is that YOU never call the
StartServiceCtrlDispatcher method in a user session - the
StartServiceCtrlDispatcher function is always and only ever called when SCM
starts the exe. Internally, SCM is waiting for the call to
StartServiceCtrlDispatcher - but only after it has strated the process in
response to a call to StartService, and that wait by the SCM is associated
with a service registration block. If that block is not set up, any call to
StartServiceCtrlDispatcher for the service fails..

If you want to start the service during installation, then open the SCM and
call StartService.

If you have bundled the installation and the ServiceMain into one process
exe (and that is a very good thing to do), then you have to set up control
flow to allow for EITHER the installation or the service to run, but never
both.

With that, you can see the problem with your service code here:

if(InstallService() == TRUE) {
if (StartServiceCtrlDispatcher(DispatchTable) == 0)
}


Consider the following for a revised main for you service app:

/* ******************************************* */
SERVICE_TABLE_ENTRY DispatchTable[] = {
{ "DZSvc", (LPSERVICE_MAIN_FUNCTION) ServiceMain },
{ NULL, NULL }};

/* ******************************************* */

/* ******************************************* */
int main(int argc, char *argv[] ) {
bool blRun = (argc == 0);
bool blInstall = (argc > 1) && (strcimp(argv[1],"-I") == 0);
bool blRemove = (argc > 1) && (stricmp(argv[1],"-R") == 0);

if (blInstall) InstallService();
else if (blRemove) RemoveService();
else if(blRun) StartServiceCtrlDispatcher(DispatchTable);

}

regards
roy fine
Post by Shane G. Brodie
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
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
Post by Shane G. Brodie
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;
}
}
Shane G. Brodie
2003-11-27 19:11:19 UTC
Permalink
Thanks muchly Roy.

Excellent explanation. I now see the error of my ways ...
I can now crawl forward several more small steps ...

Regards

Shane

Loading...