| Main |Next |Site Index|Download|Disclaimer|Privacy|


 

 

 

 

 

 

WINDOWS SERVICES & PROCESS: A SUPPLEMENTARY NOTE

 

 

 

 

 

 

 

Windows Service: Functions used in program examplesofWindows Services part 1 andWindows Services part 2 wherever applicable. To learn about function you can jump toC & C++ functions tutorials.

 

 

The Page Index

  1. ServiceMain()

  2. StartServiceCtrlDispatcher()

  3. RegisterServiceCtrlHandler()

  4. RegisterServiceCtrlHandlerEx()

  5. SetServiceStatus()

  6. Handler()

  7. HandlerEx()

  8. StartService()

  9. CreateProcess()

 

 

ServiceMain()

 

Item

Description

Function

ServiceMain().

Use

As the starting point fora service. The LPSERVICE_MAIN_FUNCTIONtype defines a pointer to this callback function.ServiceMain()is a placeholder for an application-defined function name.

Prototype

VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv);

Parameters

dwArgc - [in] Number of argumentsin the lpszArgv array.

lpszArgv - [in] Pointer to an arrayof pointers to null-terminated argument strings. The firstargument in the array is the name of the service, and subsequentarguments are any strings passed to the service by the processthat called the StartService()function to start the service.

Return value

This function does not returna value.

Include file

<windows.h>

Remark

See below.

 

Table 1.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Some Remarks

 

A service program can start one or more services. A service process hasa SERVICE_TABLE_ENTRYstructure for each service that it can start. The structure specifies the servicename and a pointer to the ServiceMain()function for that service.When the service control manager receives a request to start a service,it starts the service process (if it is not already running). The main thread of the service processcalls the StartServiceCtrlDispatcher()function with a pointer to an array of SERVICE_TABLE_ENTRYstructures. Then the service control manager sends a start request to the servicecontrol dispatcher for this service process. The service control dispatchercreates a new thread to execute the ServiceMain() function of the service beingstarted.The ServiceMain() function should immediatelycall the RegisterServiceCtrlHandlerEx()function to specify a HandlerEx()function to handle control requests. Next, it should call theSetServiceStatus()function to send status information to the service control manager. After thesecalls, the function should complete the initialization of the service. Do notattempt to start another service in the ServiceMain()function.The Service Control Manager (SCM) waits until the service reports a statusof SERVICE_RUNNING.It is recommended that the service reports this status as quickly as possible,as other components in the system that require interaction with SCM will beblocked during this time. Some functions may require interaction with the SCMeither directly or indirectly. The SCM locks the service control database duringinitialization, so if a service attempts to call StartService()during initialization, the call will block. When the service reports to theSCM that it has successfully started, it can call StartService().If the service requires another service to be running, the service should setthe required dependencies.Furthermore, you should not call any system functions during service initialization.The service code should call system functions only after it reports a statusof SERVICE_RUNNING.The ServiceMain() function should call theRegisterWaitForSingleObject()function on an event and exit. This will terminate the thread that is runningthe ServiceMain()function, but will not terminate the service. The service control handler shouldsignal this event when the service stops. A thread from the thread pool willexecute the code that performs the cleanup and callsSetServiceStatus()with SERVICE_STOPPED. Windows NT:  On earlier platforms whereRegisterWaitForSingleObject()is not available, it is common practice for the thread executing theServiceMain()function to wait on an event that is signaled by the service control handlerwhen the service stops. When the event is signaled, ServiceMainitself()performs any cleanup and calls SetServiceStatus()with SERVICE_STOPPED.

 

StartServiceCtrlDispatcher()

 

Item

Description

Function

StartServiceCtrlDispatcher().

Use

Connects the main thread of a serviceprocess to the service control manager, which causes the threadto be the service control dispatcher thread for the calling process.

Prototype

BOOL StartServiceCtrlDispatcher( const LPSERVICE_TABLE_ENTRY  lpServiceTable);

Parameters

lpServiceTable - [in] Pointer to an array ofSERVICE_TABLE_ENTRYstructures containing one entry for each service that can executein the calling process. The members of the last entry in the tablemust have NULL values to designate the end of the table.

Return value

See below.

Include file

<windows.h>

Remark

Implemented as Unicode and ANSI versions.More remarks below.

 

Table 2.

 

Return Values

 

If the function succeeds, the return value is nonzero. If the function fails,the return value is zero. To get extended error information, callGetLastError().The following error code can be set by the service control manager. Other errorcodes can be set by the registry functions that are called by the service controlmanager.

 

Return code

Description

ERROR_FAILED_SERVICE_CONTROLLER_CONNECT

Typically, this error indicates thatthe program is being run as a console application rather than asa service.

If the program will be run as a consoleapplication for debugging purposes, structure it such that service-specificcode is not called when this error is returned.

ERROR_INVALID_DATA

The specified dispatch table containsentries that are not in the proper format.

ERROR_SERVICE_ALREADY_RUNNING

The process has already calledStartServiceCtrlDispatcher().Each process can call StartServiceCtrlDispatcher()only one time. For Windows NT:  This value is not supported.

 

Table 3

 

Some Remarks

 

When the service control manager starts a service process, it waits forthe process to call the StartServiceCtrlDispatcher()function. The main thread of a service process should make this call as soonas possible after it starts up. If StartServiceCtrlDispatcher()succeeds, it connects the calling thread to the service control manager anddoes not return until all running services in the process have terminated. Theservice control manager uses this connection to send control and service startrequests to the main thread of the service process. The main thread acts asa dispatcher by invoking the appropriate HandlerEx()function to handle control requests, or by creating a new thread to executethe appropriate ServiceMain()function when a new service is started.The lpServiceTable parameter contains an entryfor each service that can run in the calling process. Each entry specifies theServiceMain()function for that service. For SERVICE_WIN32_SHARE_PROCESS services, eachentry must contain the name of a service. This name is the service name thatwas specified by the CreateService()function when the service was installed. For SERVICE_WIN32_OWN_PROCESSservices, the service name in the table entry is ignored.If a service runs in its own process, the main thread of the service processshould immediately call StartServiceCtrlDispatcher().All initialization tasks are done in the service's ServiceMain()function when the service is started. If multiple services share a process andsome common process-wide initialization needs to be done before anyServiceMain()function is called, the main thread can do the work before callingStartServiceCtrlDispatcher(),as long as it takes less than 30 seconds. Otherwise, another thread must becreated to do the process-wide initialization, while the main thread callsStartServiceCtrlDispatcher()and becomes the service control dispatcher. Any service-specific initializationshould still be done in the individual service main functions.

 

RegisterServiceCtrlHandler()

 

Item

Description

Function

RegisterServiceCtrlHandler().

Use

A service calls theRegisterServiceCtrlHandler()function to register a function to handle its service control requests.This function has been superseded by theRegisterServiceCtrlHandlerEx()function. A service can use either function, but the new functionsupports user-defined context data, and the new handler functionsupports additional extended control codes.

Prototype

SERVICE_STATUS_HANDLE RegisterServiceCtrlHandler(LPCTSTR lpServiceName, LPHANDLER_FUNCTION   lpHandlerProc);

Parameters

lpServiceName - [in] Pointer to a null-terminatedstring that specifies the name of the service run by the callingthread. This is the service name that the service control programspecified in the CreateService()function when creating the service.If the service type isSERVICE_WIN32_OWN_PROCESS,the function does not verify that the specified name is valid, becausethere is only one registered service in the process.

lpHandlerProc - [in] Pointer to the handler functionto be registered.

Return value

See below.

Include file

<windows.h>

Remark

Implemented as Unicode and ANSI versions.The ServiceMain()function of a new service should immediately call theRegisterServiceCtrlHandler()function to register a control handler function with the controldispatcher. This enables the control dispatcher to invoke the specifiedfunction when it receives control requests for this service. Thethreads of the calling process can use the service status handlereturned by this function to identify the service in subsequentcalls to the SetServiceStatus()function.

The RegisterServiceCtrlHandler()function must be called before the first SetServiceStatus()call because RegisterServiceCtrlHandler()returns a service status handle for the caller to use so that noother service can inadvertently set this service status. In addition,the control handler must be in place to receive control requestsby the time the service specifies the controls it accepts throughthe SetServiceStatus()function.When the control handler functionis invoked with a control request, it must call SetServiceStatus()to notify the service control manager of its current status, regardlessof whether the status of the service has changed. The service statushandle does not have to be closed.

 

Table 4.

 

Return Values

 

If the function succeeds, the return value is a service status handle. Ifthe function fails, the return value is zero. To get extended error information,call GetLastError().The following error codes can be set by the service control manager. Other errorcodes can be set by the registry functions that are called by the service controlmanager.

 

Return code

Description

ERROR_INVALID_NAME

The specified service name is invalid.

ERROR_SERVICE_DOES_NOT_EXIST

The specified service does not exist.

 

Table 5

 

RegisterServiceCtrlHandlerEx()

 

Item

Description

Function

StartServiceCtrlDispatcherEx().

Use

A service calls theRegisterServiceCtrlHandlerEx()function to register a function to handle its service control requests.This function supersedes the RegisterServiceCtrlHandler() function.A service can use either function, but the new function supportsuser-defined context data, and the new handler function supportsadditional extended control codes.

Prototype

SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerEx(LPCTSTR lpServiceName,

 LPHANDLER_FUNCTION_EX lpHandlerProc,LPVOID  lpContext);

Parameters

lpServiceName - [in] Pointer to a null-terminatedstring that specifies the name of the service run by the callingthread. This is the service name that the service control programspecified in the CreateService()function when creating the service.

lpHandlerProc - [in] Pointer to the handler functionto be registered.

lpContext - [in] User-defined data. This parameter,which is passed to the handler function, can help identify the servicewhen multiple services share a process.

Return value

If the function succeeds, the returnvalue is a service status handle. If the function fails, the returnvalue is zero. To get extended error information, callGetLastError().The following error codes can be set by the service control manager.Other error codes can be set by the registry functions that arecalled by the service control manager.

  1. ERROR_INVALID_NAME -The specified service name is invalid.

  2. ERROR_SERVICE_DOES_NOT_EXIST- The specified service does not exist.

Include file

<windows.h>

Remark

Implemented as Unicode and ANSI versions.TheServiceMain() function of a new service should immediatelycall the RegisterServiceCtrlHandlerEx()function to register a control handler function with the controldispatcher. This enables the control dispatcher to invoke the specifiedfunction when it receives control requests for this service. Thethreads of the calling process can use the service status handlereturned by this function to identify the service in subsequentcalls to the SetServiceStatus()function.The RegisterServiceCtrlHandlerEx()function must be called before the firstSetServiceStatus()call because RegisterServiceCtrlHandlerEx()returns a service status handle for the caller to use so that noother service can inadvertently set this service status. In addition,the control handler must be in place to receive control requestsby the time the service specifies the controls it accepts throughthe SetServiceStatus()function.When the control handler functionis invoked with a control request, it must call SetServiceStatus()to notify the service control manager of its current status, regardlessof whether the status of the service has changed. The service statushandle does not have to be closed.

 

Table 6.

 

SetServiceStatus()

 

Item

Description

Function

SetServiceStatus().

Use

Updates the service control manager'sstatus information for the calling service.

Prototype

BOOL SetServiceStatus( SERVICE_STATUS_HANDLE hServiceStatus,LPSERVICE_STATUS lpServiceStatus);

Parameters

hServiceStatus - [in] Handle to the status informationstructure for the current service. This handle is returned by theRegisterServiceCtrlHandlerEx()function.

lpServiceStatus - [in] Pointer to theSERVICE_STATUSstructure that contains the latest status information for the callingservice.

Return value

If the function succeeds, the returnvalue is nonzero. If the function fails, the return value is zero.To get extended error information, call GetLastError().The following error codes can be set by the service control manager.Other error codes can be set by the registry functions that arecalled by the service control manager.

  1. ERROR_INVALID_DATA -The specified service status structure is invalid.

  2. ERROR_INVALID_HANDLE- The specified handle is invalid.

Include file

<windows.h>

Remark

See below.

 

Table 7.

 

Some Remarks

 

A ServiceMain()function first calls the RegisterServiceCtrlHandlerEx() function toget the service's SERVICE_STATUS_HANDLE.Then it immediately calls the SetServiceStatus() function to notify theservice control manager that its status is SERVICE_START_PENDING.During initialization, the service can provide updated status to indicate thatit is making progress but it needs more time. A common bug is for the serviceto have the main thread perform the initialization while a separate thread continuesto call SetServiceStatus()to prevent the service control manager from marking it as hung. However, ifthe main thread hangs, then the service start ends up in an infinite loop becausethe worker thread continues to report that the main thread is making progress.When a service receives a control request, the service's Handler()function must call SetServiceStatus(),even if the service's status did not change. A service can also use this functionat any time and by any thread of the service to notify the service control managerof status changes. Examples of such unsolicited status updates include:

  1. Checkpoint updates that occur when the service isin transition from one state to another.

  2. Fatal error updates that occur when the servicemust stop due to a recoverable error.

 

A service can call this function only after it has called RegisterServiceCtrlHandlerEx()to get a service status handle. If a service calls SetServiceStatus() with the dwCurrentStatemember set to SERVICE_STOPPEDand the dwWin32ExitCodemember set to a nonzero value, the following entry is written into the Systemevent log:

 

  Event ID    = 7023

  Source      = Service Control Manager

  Type        = Error

  Description = <ServiceName> terminated with the following error:

                <ExitCode>.

 

Handler()

 

Item

Description

Function

Handler().

Use

A Handler function is an application-definedcallback function used with the RegisterServiceCtrlHandler()function. A service program uses it as the control handler functionof a particular service. The LPHANDLER_FUNCTIONtype defines a pointer to this function. Handler is a placeholderfor the application-defined name.This function has been superseded by theHandlerEx() control handler function usedwith the RegisterServiceCtrlHandlerEx()function. A service can use either control handler, but the newcontrol handler supports user-defined context data and additionalextended control codes.

Prototype

VOID WINAPI Handler(DWORD fdwControl);

Parameters

Se below.

Return value

This function does not return a value.

Include file

<windows.h>

Remark

See below.

 

Table 8.

 

Parameters

 

fdwControl - [in] Control code. This parameter can be one of the following values.

 

Control code

Meaning

SERVICE_CONTROL_CONTINUE

Notifies a paused service that itshould resume.

SERVICE_CONTROL_INTERROGATE

Notifies a service that it shouldreport its current status information to the service control manager.

SERVICE_CONTROL_NETBINDADD

Notifies a network service that thereis a new component for binding. The service should bind to the newcomponent. However, this control code has been deprecated; use PnPfunctionality instead. For Windows NT:  This value is not supported.

SERVICE_CONTROL_NETBINDDISABLE

Notifies a network service that oneof its bindings has been disabled. The service should reread itsbinding information and remove the binding. However, this controlcode has been deprecated; use PnP functionality instead. For WindowsNT:  This value is not supported.

SERVICE_CONTROL_NETBINDENABLE

Notifies a network service that adisabled binding has been enabled. The service should reread itsbinding information and add the new binding. However, this controlcode has been deprecated; use PnP functionality instead. For WindowsNT:  This value is not supported.

SERVICE_CONTROL_NETBINDREMOVE

Notifies a network service that acomponent for binding has been removed. The service should rereadits binding information and unbind from the removed component. However,this control code has been deprecated; use PnP functionality instead.For Windows NT:  This value is not supported.

SERVICE_CONTROL_PARAMCHANGE

Notifies a service that its startupparameters have changed. The service should reread its startup parameters.For Windows NT:  This value is not supported.

SERVICE_CONTROL_PAUSE

Notifies a service that it shouldpause.

SERVICE_CONTROL_SHUTDOWN

Notifies a service that the systemis shutting down so the service can perform cleanup tasks.

For more information, see Remarkssection.

SERVICE_CONTROL_STOP

Notifies a service that it shouldstop.

 

Table 9

 

This parameter can also be a user-defined control code, as described inthe following table.

 

Control code

Meaning

Range 128 to 255.

The service defines the action associatedwith the control code.

 

Table 10

 

Some Remarks

 

When a service is started, its ServiceMain()function should immediately call the RegisterServiceCtrlHandler()function to specify a Handler() functionto process control requests. The control dispatcher in the main thread of aservice process invokes the control handler function for the specified servicewhenever it receives a control request from the service control manager. Afterprocessing the control request, the control handler must call theSetServiceStatus()function to report its current status to the service control manager. When theservice control manager sends a control code to a service, it waits for thehandler function to return before sending additional control codes to otherservices. If the handler function does not return promptly, it may block otherservices from receiving control codes.

The SERVICE_CONTROL_SHUTDOWN control code shouldonly be processed by services that must absolutely clean up during shutdown,because there is a limited time (about 20 seconds) available for service shutdown.After this time expires, system shutdown proceeds regardless of whether serviceshutdown is complete. Note that if the system is left in the shutdown state(not restarted or powered down), the service continues to run.

If the service needs more time to clean up, it should sendSTOP_PENDINGstatus messages, along with a wait hint, so the service controller knows howlong to wait before reporting to the system that service shutdown is complete.However, to prevent a service from stopping shutdown, there is a limit to howlong the service controller will wait. To change this time limit, modify theWaitToKillServiceTimeout()value in the followingregistry key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control

HandlerEx()

 

Item

Description

Function

HandlerEx().

Use

Is an application-defined callbackfunction used with the RegisterServiceCtrlHandlerEx() function.A service program can use it as the control handler function ofa particular service. The LPHANDLER_FUNCTION_EXtype defines a pointer to this function.HandlerEx()is a placeholder for the application-defined name. This functionsupersedes the Handler()control handler function used with the RegisterServiceCtrlHandler()function. A service can use either control handler, but the newcontrol handler supports user-defined context data and additionalextended control codes.

Prototype

DWORD WINAPI HandlerEx(DWORD dwControl,DWORD dwEventType,LPVOID lpEventData,LPVOID lpContext);

Parameters

See below.

Return value

The return value for this functiondepends on the control code received. The rules for this returnvalue are as follows.

  1. If your service does not handle thecontrol, return ERROR_CALL_NOT_IMPLEMENTED.

  2. If your service handlesSERVICE_CONTROL_DEVICEEVENT,return NO_ERRORto grant the request and an error code to deny the request.

  3. If your service handlesSERVICE_CONTROL_HARDWAREPROFILECHANGE,return NO_ERRORto grant the request and an error code to deny the request.

  4. If your service handlesSERVICE_CONTROL_POWEREVENT,return NO_ERRORto grant the request and an error code to deny the request.

  5. For all other control codes your servicehandles, return NO_ERROR.

Include file

<windows.h>

Remark

See below.

 

Table 11.

 

Parameters

 

dwControl - [in] Control code. This parameter can be one of the following values.

 

Control code

Meaning

SERVICE_CONTROL_CONTINUE

Notifies a paused service that itshould resume.

SERVICE_CONTROL_INTERROGATE

Notifies a service to report itscurrent status information to the service control manager.

SERVICE_CONTROL_NETBINDADD

Notifies a network service that thereis a new component for binding. The service should bind to the newcomponent. However, this control code has been deprecated; use PnPfunctionality instead.Windows NT:  This value is notsupported.

SERVICE_CONTROL_NETBINDDISABLE

Notifies a network service that oneof its bindings has been disabled. The service should reread itsbinding information and remove the binding. However, this controlcode has been deprecated; use PnP functionality instead.Windows NT:  This value is notsupported.

SERVICE_CONTROL_NETBINDENABLE

Notifies a network service that adisabled binding has been enabled. The service should reread itsbinding information and add the new binding. However, this controlcode has been deprecated; use PnP functionality instead.Windows NT:  This value is notsupported.

SERVICE_CONTROL_NETBINDREMOVE

Notifies a network service that acomponent for binding has been removed. The service should rereadits binding information and unbind from the removed component. However,this control code has been deprecated; use PnP functionality instead.Windows NT:  This value is notsupported.

SERVICE_CONTROL_PARAMCHANGE

Notifies a service that service-specificstartup parameters have changed. The service should reread its startupparameters.Windows NT:  This value is notsupported.

SERVICE_CONTROL_PAUSE

Notifies a service that it shouldpause.

SERVICE_CONTROL_SHUTDOWN

Notifies a service that the systemis shutting down so the service can perform cleanup tasks.For more information, see Remarks.

SERVICE_CONTROL_STOP

Notifies a service that it shouldstop.

 

Table 12

 

This parameter can also be one of the following extended control codes.Note that these control codes are not supported by the Handler()function.

 

Control code

Meaning

SERVICE_CONTROL_DEVICEEVENT

Notifies a service of device events.The service must have registered to receive these notificationsusing the RegisterDeviceNotification()function. For Windows NT:  This value is not supported.

SERVICE_CONTROL_HARDWAREPROFILECHANGE

Notifies a service that the computer'shardware profile has changed. For Windows NT:  This value isnot supported.

SERVICE_CONTROL_POWEREVENT

Notifies a service of system powerevents. For Windows NT:  This value is not supported.

SERVICE_CONTROL_SESSIONCHANGE

Notifies a service of session changeevents. For Windows 2000/NT:  This value is not supported.

 

Table 13

 

This parameter can also be a user-defined control code, as described inthe following table.

 

Control code

Meaning

Range 128 to 255.

The service defines the action associatedwith the control code.

 

Table 14

 

dwEventType - [in] Type of event that has occurred. This parameter is used ifdwControl isSERVICE_CONTROL_DEVICEEVENT,SERVICE_CONTROL_HARDWAREPROFILECHANGE,SERVICE_CONTROL_POWEREVENT,or SERVICE_CONTROL_SESSIONCHANGE.Otherwise, it is zero. If dwControl is SERVICE_CONTROL_DEVICEEVENT,this parameter can be one of the following values:

  1. DBT_DEVICEARRIVAL

  2. DBT_DEVICEREMOVECOMPLETE

  3. DBT_DEVICEQUERYREMOVE

  4. DBT_DEVICEQUERYREMOVEFAILED

  5. DBT_DEVICEREMOVEPENDING

  6. DBT_CUSTOMEVENT

 

If dwControl is SERVICE_CONTROL_HARDWAREPROFILECHANGE,this parameter can be one of the following values:

  1. DBT_CONFIGCHANGED

  2. DBT_QUERYCHANGECONFIG

  3. DBT_CONFIGCHANGECANCELED

 

If dwControl is SERVICE_CONTROL_POWEREVENT,this parameter can be one of the values specified in thewParamparameter of the WM_POWERBROADCASTmessage.If dwControl is SERVICE_CONTROL_SESSIONCHANGE,this parameter can be one of the values specified in thewParamparameter of the WM_WTSSESSION_CHANGEmessage.

lpEventData - [in] Additional device information, if required. The format of this datadepends on the value of the dwControl anddwEventTypeparameters. If dwEventTypeis SERVICE_CONTROL_DEVICEEVENT,this data corresponds to the lParam parameter that applications receiveas part of a WM_DEVICECHANGEmessage. If dwEventTypeis SERVICE_CONTROL_POWEREVENT,this data corresponds to the lParam parameter that applications receiveas part of a WM_POWERBROADCASTmessage. If dwEventTypeis SERVICE_CONTROL_SESSIONCHANGE,this parameter is a WTSSESSION_NOTIFICATIONstructure.

lpContext - [in] User-defined data passed from RegisterServiceCtrlHandlerEx().When multiple services share a process, the lpContext parametercan help identify the service.

 

Some Remarks

 

When a service is started, its ServiceMain()function should immediately call the RegisterServiceCtrlHandlerEx()function to specify a HandlerEx()function to process control requests. To specify the control codes to be accepted,use the SetServiceStatus()and RegisterDeviceNotification()functions.The control dispatcher in the main thread of a service invokes the controlhandler function for the specified service whenever it receives a control requestfrom the service control manager. After processing the control request, thecontrol handler must call SetServiceStatus()to report its current status to the service control manager.When the service control manager sends a control code to a service, it waitsfor the handler function to return before sending additional control codes toother services. If the handler function does not return promptly, it may blockother services from receiving control codes.The SERVICE_CONTROL_SHUTDOWN control code shouldonly be processed by services that must absolutely clean up during shutdown,because there is a limited time (about 20 seconds) available for service shutdown.After this time expires, system shutdown proceeds regardless of whether serviceshutdown is complete. Note that if the system is left in the shutdown state(not restarted or powered down), the service continues to run.If the service needs more time to clean up, it should sendSTOP_PENDINGstatus messages, along with a wait hint, so the service controller knows howlong to wait before reporting to the system that service shutdown is complete.However, to prevent a service from stopping shutdown, there is a limit to howlong the service controller will wait. To change this time limit, modify theWaitToKillServiceTimeoutvalue in the following registry key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control

Be sure to handle Plug and Play deviceevents as quickly as possible; otherwise, the system may become unresponsive.If your event handler is to perform an operation that may block execution (suchas I/O), it is best to start another thread to perform the operation asynchronously.

 

StartService()

 

Item

Description

Function

StartService().

Use

Starts a service.

Prototype

BOOL StartService(SC_HANDLE hService,DWORD dwNumServiceArgs,LPCTSTR* lpServiceArgVectors);

Parameters

hService - [in] Handle to the service. Thishandle is returned by the OpenService()or CreateService()function, and it must have the SERVICE_STARTaccess right.

dwNumServiceArgs - [in] Number of strings in the lpServiceArgVectorsarray. If lpServiceArgVectors is NULL, this parametercan be zero.

lpServiceArgVectors - [in] Pointer to an array of pointersto null-terminated strings to be passed to a service as arguments.Driver services do not receive these arguments. If no argumentsare passed to the service, this parameter can be NULL. The serviceaccesses these arguments through its ServiceMain() function. The first argument(argv[0])is the name of the service by default, followed by the arguments,if any, in the lpServiceArgVectorsarray.

Return value

See below.

Include file

<windows.h>

Remark

Implemented as Unicode and ANSI versions.More remarks below.

 

Table 15.

 

Return Values

 

If the function succeeds, the return value is nonzero. If the function fails,the return value is zero. To get extended error information, callGetLastError().The following error codes can be set by the service control manager. Otherscan be set by the registry functions that are called by the service controlmanager.

 

Return code

Description

ERROR_ACCESS_DENIED

The handle does not have theSERVICE_STARTaccess right.

ERROR_INVALID_HANDLE

The handle is invalid.

ERROR_PATH_NOT_FOUND

The service binary file could notbe found.

ERROR_SERVICE_ALREADY_RUNNING

An instance of the service is alreadyrunning.

ERROR_SERVICE_DATABASE_LOCKED

The database is locked.

ERROR_SERVICE_DEPENDENCY_DELETED

The service depends on a servicethat does not exist or has been marked for deletion.

ERROR_SERVICE_DEPENDENCY_FAIL

The service depends on another servicethat has failed to start.

ERROR_SERVICE_DISABLED

The service has been disabled.

ERROR_SERVICE_LOGON_FAILED

The service could not be logged on.This error occurs if the service was started from an account thatdoes not have the "Logon as a service" right.

ERROR_SERVICE_MARKED_FOR_DELETE

The service has been marked for deletion.

ERROR_SERVICE_NO_THREAD

A thread could not be created forthe service.

ERROR_SERVICE_REQUEST_TIMEOUT

The process for the service was started,but it did not call StartServiceCtrlDispatcher(), or the threadthat called StartServiceCtrlDispatcher()may be blocked in a control handler function.

 

Table 16

 

 

Some Remarks

 

When a driver service is started, the StartService()function does not return until the device driver has finished initializing.When a service is started, the Service Control Manager (SCM) spawns the serviceprocess, if necessary. If the specified service shares a process with otherservices, the required process may already exist. TheStartService()function does not wait for the first status update from the new service, becauseit can take a while.

Instead, it returns when the SCM receives notificationfrom the service control dispatcher that the ServiceMain()thread for this service was created successfully. The SCM sets the followingdefault status values before returning from StartService():

  1. Current state of the service is set toSERVICE_START_PENDING.

  2. Controls accepted is set to none (zero).

  3. TheCheckPoint valueis set to zero.

  4. TheWaitHint timeis set to 2 seconds.

 

The calling process can determine if the new service has finished its initializationby calling the QueryServiceStatus()function periodically to query the service's status. A service cannot callStartService()during initialization. The reason is that the SCM locks the service controldatabase during initialization, so a call to StartService()will block. Once the service reports to the SCM that it has successfully started,it can call StartService().As with ControlService(),StartService()will block for 30 seconds if any service is busy handling a control code. Ifthe busy service still has not returned from its handler function when the timeoutexpires, StartService()fails with ERROR_SERVICE_REQUEST_TIMEOUT.This is because the SCM processes only one service control notification at atime.

 

CreateProcess()

 

Item

Description

Function

CreateProcess().

Use

Creates a new process and its primarythread. The new process runs the specified executable file in thesecurity context of the calling process. If the calling processis impersonating another user, the new process uses the token forthe calling process, not the impersonation token. To run the newprocess in the security context of the user represented by the impersonationtoken, use the CreateProcessAsUser()or CreateProcessWithLogonW()function.

Prototype

BOOL CreateProcess(LPCTSTR lpApplicationName,LPTSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCTSTR lpCurrentDirectory,LPSTARTUPINFO lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation);

Parameters

See below.

Return value

If the function succeeds, the returnvalue is nonzero. If the function fails, the return value is zero.To get extended error information, call GetLastError().

Include file

<windows.h>

Remark

Implemented as Unicode and ANSI versions.Note that Unicode support on Windows Me/98/95 requires MicrosoftLayer for Unicode. More remarks below.

 

Table 17.

 

Parameters

 

lpApplicationName - [in] Pointer to a null-terminated string that specifies the module to execute.The specified module can be a Windows-based application. It can be some othertype of module (for example, MS-DOS or OS/2) if the appropriate subsystem isavailable on the local computer.

The string can specify the full path and file name of the module to executeor it can specify a partial name. In the case of a partial name, the functionuses the current drive and current directory to complete the specification.The function will not use the search path. If the file name does not containan extension, .exe is assumed.Therefore, if the file name extension is .com, this parameter must include the.comextension. The lpApplicationName parameter can be NULL.In that case, the module name must be the first white space-delimited tokenin the lpCommandLinestring. If you are using a long file name that contains a space, use quotedstrings to indicate where the file name ends and the arguments begin; otherwise,the file name is ambiguous. For example, consider the string "c:\programfiles\sub dir\program name". This string can be interpreted ina number of ways. The system tries to interpret the possibilities in the followingorder:

  1. c:\program.exe files\sub dir\program name

  2. c:\program files\sub.exe dir\program name

  3. c:\program files\sub dir\program.exe name

  4. c:\program files\sub dir\program name.exe

 

If the executable module is a 16-bit application, lpApplicationNameshould be NULL, and the string pointed to by lpCommandLineshould specify the executable module as well as its arguments.

lpCommandLine - [in, out] Pointer to a null-terminated string that specifies the commandline to execute. The maximum length of this string is 32K characters.Windows 2000:  The maximum length of this string isMAX_PATHcharacters.The Unicode version of this function, CreateProcessW(),will fail if this parameter is a const string.The lpCommandLine parameter can be NULL. In thatcase, the function uses the string pointed to by lpApplicationNameas the command line.If both lpApplicationName andlpCommandLineare non-NULL, the null-terminated string pointed to bylpApplicationNamespecifies the module to execute, and the null-terminated string pointed to bylpCommandLinespecifies the command line. The new process can use GetCommandLine()to retrieve the entire command line. Console processes written in C can usethe argc andargvarguments to parse the command line. Because argv[0] is themodule name, C programmers generally repeat the module name as the first tokenin the command line. If lpApplicationName is NULL, the first white-space– delimited token of the command line specifies the module name. If you areusing a long file name that contains a space, use quoted strings to indicatewhere the file name ends and the arguments begin (see the explanation for thelpApplicationNameparameter). If the file name does not contain an extension,.exeis appended. Therefore, if the file name extension is.com,this parameter must include the .com extension.If the file name ends in a period (.)with no extension, or if the file name contains a path, .exe is not appended.If the file name does not contain a directory path, the system searches forthe executable file in the following sequence:

 

  1. The directory from which the applicationloaded.

  2. The current directory for the parent process.

  3. The 32-bit Windows system directory. Usethe GetSystemDirectory()function to get the path of this directory. For WindowsMe/98/95:  The Windows systemdirectory. Use the GetSystemDirectory()function to get the path of this directory.

  1. The 16-bit Windows system directory. Thereis no function that obtains the path of this directory, but it is searched.The name of this directory is System.

  2. The Windows directory. Use theGetWindowsDirectory()function to get the path of this directory.

  3. The directories that are listed in the PATHenvironment variable.

 

The system adds a null character to the command line string to separatethe file name from the arguments. This divides the original string into twostrings for internal processing.

lpProcessAttributes - [in] Pointer to a SECURITY_ATTRIBUTESstructure that determines whether the returned handle can be inherited by childprocesses. If lpProcessAttributesis NULL, the handle cannot be inherited.The lpSecurityDescriptor member of the structurespecifies a security descriptor for the new process. IflpProcessAttributesis NULL or lpSecurityDescriptoris NULL, the process gets a default security descriptor. The ACLs in the defaultsecurity descriptor for a process come from the primary or impersonation tokenof the creator.

lpThreadAttributes - [in] Pointer to a SECURITY_ATTRIBUTESstructure that determines whether the returned handle can be inherited by childprocesses. If lpThreadAttributesis NULL, the handle cannot be inherited.The lpSecurityDescriptor member of the structurespecifies a security descriptor for the main thread. IflpThreadAttributesis NULL or lpSecurityDescriptoris NULL, the thread gets a default security descriptor. The ACLs in the defaultsecurity descriptor for a thread come from the primary or impersonation tokenof the creator.

bInheritHandles - [in] If this parameter TRUE, each inheritable handle in the calling processis inherited by the new process. If the parameter is FALSE, the handles arenot inherited. Note that inherited handles have the same value and access rightsas the original handles.

dwCreationFlags - [in] Flags that control the priority class and the creation of the process.This parameter also controls the new process's priority class, which isused to determine the scheduling priorities of the process's threads. If noneof the priority class flags is specified, the priority class defaults toNORMAL_PRIORITY_CLASSunless the priority class of the creating process isIDLE_PRIORITY_CLASSor BELOW_NORMAL_PRIORITY_CLASS.In this case, the child process receives the default priority class of the callingprocess.

lpEnvironment - [in] Pointer to an environment block for the new process. If this parameteris NULL, the new process uses the environment of the calling process.An environment block consists of a null-terminated block of null-terminatedstrings. Each string is in the form:name=value. Because the equal sign is used as a separator, it must not be used in thename of an environment variable.An environment block can contain either Unicode or ANSI characters. If theenvironment block pointed to by lpEnvironmentcontains Unicode characters, be sure that dwCreationFlags includesCREATE_UNICODE_ENVIRONMENT.Note that an ANSI environment block is terminated by two zero bytes: onefor the last string, one more to terminate the block. A Unicode environmentblock is terminated by four zero bytes: two for the last string, two more toterminate the block.

lpCurrentDirectory - [in] Pointer to a null-terminated string that specifies the full path tothe current directory for the process. The string can also specify a UNC path.If this parameter is NULL, the new process will have the same current driveand directory as the calling process. This feature is provided primarily forshells that need to start an application and specify its initial drive and workingdirectory.

lpStartupInfo - [in] Pointer to a STARTUPINFOstructure that specifies the window station, desktop, standard handles, andappearance of the main window for the new process.

lpProcessInformation - [out] Pointer to a PROCESS_INFORMATIONstructure that receives identification information about the new process.Handles inPROCESS_INFORMATIONmust be closed with CloseHandle()when they are no longer needed.

 

Some Remarks

 

The process is assigned a process identifier. The identifier is valid untilthe process terminates. It can be used to identify the process, or specifiedin the OpenProcess() function to open a handle tothe process. The initial thread in the process is also assigned a thread identifier.It can be specified in the OpenThread()function to open a handle to the thread. The identifier is valid until the threadterminates and can be used to uniquely identify the thread within the system.These identifiers are returned in the PROCESS_INFORMATIONstructure.The calling thread can use the WaitForInputIdle()function to wait until the new process has finished its initialization and iswaiting for user input with no input pending. This can be useful for synchronizationbetween parent and child processes, because CreateProcess()returns without waiting for the new process to finish its initialization. Forexample, the creating process would use WaitForInputIdle() before trying to finda window associated with the new process.The preferred way to shut down a process is by using the ExitProcess()function, because this function sends notification of approaching terminationto all DLLs attached to the process. Other means of shutting down a processdo not notify the attached DLLs. Note that when a thread callsExitProcess(),other threads of the process are terminated without an opportunity to executeany additional code (including the thread termination code of attached DLLs).

A parent process can directly alter the environment variables of a childprocess during process creation. This is the only situation when a process candirectly change the environment settings of another process. If an applicationprovides an environment block, the current directory information of the systemdrives is not automatically propagated to the new process. For example, thereis an environment variable named =C: whosevalue is the current directory on drive C. An application must manually passthe current directory information to the new process. To do so, the applicationmust explicitly create these environment variable strings, sort them alphabetically(because the system uses a sorted environment), and put them into the environmentblock. Typically, they will go at the front of the environment block, due tothe environment block sort order.

One way to obtain the current directory information for a drive X is tocall GetFullPathName("X:",. .).That avoids an application having to scan the environment block. If the fullpath returned is X:\, there isno need to pass that value on as environment data, since the root directoryis the default current directory for drive X of a new process.Note:  The name of the executable in the command line that the operatingsystem provides to a process is not necessarily identical to that in the commandline that the calling process gives to the CreateProcess()function. The operating system may prepend a fully qualified path to an executablename that is provided without a fully qualified path.When a process is created with CREATE_NEW_PROCESS_GROUPspecified, an implicit call to SetConsoleCtrlHandler(NULL,TRUE) is madeon behalf of the new process; this means that the new process has CTRL+C disabled.This lets shells handle CTRL+C themselves, and selectively pass that signalon to sub-processes. CTRL+BREAK is not disabled, and may be used to interruptthe process/process group.For Windows Me/98/95:  CreateProcessW()is supported by the Microsoft Layer for Unicode. To use this, you must add certainfiles to your application, as outlined in Microsoft Layer for Unicode on WindowsMe/98/95 Systems.

 

Security Remarks

 

The first parameter, lpApplicationName,can be NULL, in which case the executable name must be in the white space-delimitedstring pointed to by lpCommandLine.If the executable or path name has a space in it, there is a risk that a differentexecutable could be run because of the way the function parses spaces. The followingexample is dangerous because the function will attempt to run "Program.exe",if it exists, instead of "MyApp.exe".

CreateProcess(NULL, "C:\\Program Files\\MyApp", ...)

If a malicious user were to create an application called "Program.exe"on a system, any program that incorrectly calls CreateProcess()using the Program Files directorywill run this application instead of the intended application. To avoid thisproblem, do not pass NULL for lpApplicationName.If you do pass NULL for lpApplicationName,use quotation marks around the executable path in lpCommandLine,as shown in the example below.

CreateProcess(NULL, "\"C:\\Program Files\\MyApp.exe\" -L -S", ...)

---------------------------------------------------------Part1/4----------------------------------------------------

 

 

 

 

 

 

 

Furtherreading and digging:

 

  1. Microsoft Visual C++, on-lineMSDN.

  2. Structure, enum, union and typedef story can be foundatC enum, typedef, define etc..

  3. For Multi bytes, Unicode characters and Localizationplease refer toUnicode & Multi-byte 1 (Story) andUnicode & Multi byte 2 (Implementation).

  4. Windows data type information isinWindows data type.

  5. Check the best selling C / C++ and Windowsbooks at Amazon.com.

 

 

 

| Main |Next |Site Index|Download|Disclaimer|Privacy|