StartServiceCtrlDispatcher

Nov 24, 2010 at 2:12am
Dear fellow programmers,

Congratulations for your extremely useful and nice Web and C++ tutorial (which I read eagerly)! I have invested a couple of days digressing about a problem, and I cannot find out the solution.

I am "migrating" a piece of software from UNIX to Windows environment, and I would like it to behave as a Windows Service. Actually, Microsoft Support Web provides a clear example (http://msdn.microsoft.com/en-us/library/bb540476%28v=VS.85%29.aspx) which I have compiled it, and it works fine. No problem at all, yet. The example provided by Microsoft in such Web is written in raw C and I would like to re-write it in a C++ style, following Object Orient paradigm (no reason why, it is just because I am very bored ;) ).

I thought it should be pretty easy and quick (variable ->variable data member, function -> member function). The part that is causing the problems is the following: (Firstly I will show you a fragment of the working example provided by Microsoft (the cornerstone for the issue), then a scribble of what I am trying, and finally how to reproduce the erroneous behavior with original Microsoft's example):


/* Original code from Microsoft example */
/* Only installation fragment is shown (because i guess the problem is around here ...) */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void __cdecl _tmain(int argc, TCHAR *argv[]) 
{ 

    // If command-line parameter is "install", install the service. 
    // Otherwise, the service is probably being started by the SCM.

    if( lstrcmpi( argv[1], TEXT("install")) == 0 )
    {
        SvcInstall();
        return;
    }

    // TO_DO: Add any additional services for the process to this table.
    SERVICE_TABLE_ENTRY DispatchTable[] = 
    { 
        { SVCNAME, (LPSERVICE_MAIN_FUNCTION) SvcMain }, 
        { NULL, NULL } 
    }; 
 
    // This call returns when the service has stopped. 
    // The process should simply terminate when the call returns.


    if (!StartServiceCtrlDispatcher( DispatchTable )) 
    { 
        SvcReportEvent(TEXT("XXX_StartServiceCtrlDispatcher")); 
    } 
} 


#####################################################################

/* My code would look like this after ruining the previous example up */
// Installation and start-up fragment
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
void __cdecl _tmain(int argc, TCHAR *argv[]) 
{

	HANDLE wThread[numThreads];

	wThread[0]= CreateThread(NULL, 0, InstallMain, NULL, 0, NULL);
	WaitForSingleObject( wThread[0], INFINITE );
	
	wThread[1]= CreateThread(NULL, 0, StartMain, NULL, 0, NULL);
	WaitForSingleObject( wThread[1], INFINITE );

} 

DWORD WINAPI InstallMain ( LPVOID arg )
{
	Svc::fileLog << "$$$ : Entering InstallMain " << endl;
	Svc::SvcInstall();
	return 0;

        /* ?????? This is the mother of the lamb ... StartServiceCtrlDispatcher */
	SERVICE_TABLE_ENTRY DispatchTable[] = 
	{
		{ SVCNAME, (LPSERVICE_MAIN_FUNCTION) ServiceMain }, 
		{ NULL, NULL } 
	};

	Svc::fileLog << "$$$ : Before StartServiceCtrlDispatcher " << endl;
	if (!StartServiceCtrlDispatcher( DispatchTable )) 
	{ 
		Svc::fileLog << "$$$ : WTF ???" << endl;
	}

}

DWORD WINAPI StartMain ( LPVOID arg )
{
	Svc::fileLog << "$$$ : Entering StartMain " << endl;
	Svc::DoStartSvc();
	return 0;
}


VOID WINAPI ServiceMain( DWORD dwArgc, LPTSTR *lpszArgv )
{
	Svc::fileLog << "$$$ : Entering ServiceMain " << endl;
	Svc::SvcMain( dwArgc, lpszArgv );

}



The result that I ALWAYS get (I have done several trials using differnt approachs) is always the same: the service is installed but it is not able to start-up. I get exactly the same result as if, in the original Microsoft's code, I would remove the StartServiceCtrlDispatcher part, as follow:


// Installation fragment
1
2
3
4
5
6
7
8
9
10
11
void __cdecl _tmain(int argc, TCHAR *argv[]) 
{ 
    // If command-line parameter is "install", install the service. 
    // Otherwise, the service is probably being started by the SCM.

    if( lstrcmpi( argv[1], TEXT("install")) == 0 )
    {
        SvcInstall();
        return;
    }
} 


Sorry for the mesh... For sure, I am doing something wrong, but I don't know what. Please, could you give any suggestion/hint or help?

Thanks in advance and kind regards!!!
S2
Last edited on Nov 24, 2010 at 2:19am
Nov 24, 2010 at 12:59pm
The StartServiceCtrlDispatcher function connects the main thread of a service process to the service control manager, which causes the thread to be the service control dispatcher thread for the calling process.
Nov 25, 2010 at 7:41pm
Thanks kbw, for you thorough support! Now it works fine.

Cheers
Topic archived. No new replies allowed.