|
Windows Service: Functions used in program examples of Windows Services 1 and Windows Services 2 wherever applicable. To learn about function you can jump to C & C++ function tutorials.
The Index:
QueryServiceStatus()
|
QueryServiceStatusEx()
Item | Description |
Function | QueryServiceStatusEx(). |
Use | Retrieves the current status of the specified service based on the specified information level. This function supersedes the QueryServiceStatus() function. QueryServiceStatusEx() returns the same information QueryServiceStatus() returns, with the addition of the process identifier and additional information for the service. |
Prototype | BOOL QueryServiceStatusEx( SC_HANDLE hService, SC_STATUS_TYPE InfoLevel, LPBYTE lpBuffer, DWORD cbBufSize, LPDWORD pcbBytesNeeded); |
Parameters | hService - [in] Handle to the service. This handle is returned by the CreateService() or OpenService() function, and it must have the SERIVCE_QUERY_STATUS access right. InfoLevel - [in] Service attributes to be returned. Use SC_STATUS_PROCESS_INFO to retrieve the service status information. The lpBuffer parameter is a pointer to a SERVICE_STATUS_PROCESS structure. Currently, no other information levels are defined. lpBuffer - [out] Pointer to the buffer that receives the status information. The format of this data depends on the value of the InfoLevel parameter. The maximum size of this array is 8K bytes. To determine the required size, specify NULL for this parameter and 0 for the cbBufSize parameter. The function will fail and GetLastError() will return ERROR_INSUFFICIENT_BUFFER. The pcbBytesNeeded parameter will receive the required size. cbBufSize - [in] Size of the buffer pointed to by the lpBuffer parameter, in bytes. pcbBytesNeeded - [out] Pointer to a variable that receives the number of bytes needed to store all status information, if the function fails with ERROR_INSUFFICIENT_BUFFER. |
Return value | See below. |
Include file | <windows.h> |
Remark | The QueryServiceStatusEx() function returns the most recent service status information reported to the service control manager. If the service just changed its status, it may not have updated the service control manager yet. Applications can find the current service status by querying the service directly by using the ControlService() function with the SERVICE_CONTROL_INTERROGATE control code. The process identifier returned in the SERVICE_STATUS_PROCESS structure is valid provided that the state of the service is one of SERVICE_RUNNING, SERVICE_PAUSE_PENDING, SERVICE_PAUSED, or SERVICE_CONTINUE_PENDING. If the service is in a SERVICE_START_PENDING or SERVICE_STOP_PENDING state, however, the process identifier may not be valid, and if the service is in the SERVICE_STOPPED state, it is never valid. |
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, call GetLastError(). The following errors can be returned.
Return code | Description |
ERROR_INVALID_HANDLE | The handle is invalid. |
ERROR_ACCESS_DENIED | The handle does not have the SERVICE_QUERY_STATUS access right. |
ERROR_INSUFFICIENT_BUFFER | The buffer is too small for the SERVICE_STATUS_PROCESS structure. Nothing was written to the structure. |
ERROR_INVALID_PARAMETER | The cbSize member of SERVICE_STATUS_PROCESS is not valid. |
ERROR_INVALID_LEVEL | The InfoLevel parameter contains an unsupported value. |
ERROR_SHUTDOWN_IN_PROGRESS | The system is shutting down; this function cannot be called. |
Table 3 |
GetTickCount()
Item | Description |
Function | GetTickCount(). |
Use | Retrieves the number of milliseconds that have elapsed since the system was started. It is limited to the resolution of the system timer. To obtain the system timer resolution, use the GetSystemTimeAdjustment() function. |
Prototype | DWORD GetTickCount(void); |
Parameters | This function has no parameters. |
Return value | The return value is the number of milliseconds that have elapsed since the system was started. |
Include file | <windows.h> |
Remark | The elapsed time is stored as a DWORD value. Therefore, the time will wrap around to zero if the system is run continuously for 49.7 days. If you need a higher resolution timer, use a multimedia timer or a high-resolution timer. To obtain the time elapsed since the computer was started, retrieve the System Up Time counter in the performance data in the registry key HKEY_PERFORMANCE_DATA. The value returned is an 8-byte value. |
Table 4. |
Example Code
The following example demonstrates how to use this function to wait for a time interval to pass. Due to the nature of unsigned arithmetic, this code works correctly if the return value wraps one time. If the difference between the two calls to GetTickCount() is more than 49.7 days, the return value could wrap more than one time and this code will not work; use the system time instead.
DWORD dwStart = GetTickCount();
// Stop if this has taken too long
if (GetTickCount() - dwStart >= TIMELIMIT)
Cancel();
Note that TIMELIMIT is defined as the time interval of interest to the application, in milliseconds.
EnumDependentServices()
Item | Description |
Function | EnumDependentServices(). |
Use | Retrieves the name and status of each service that depends on the specified service; that is, the specified service must be running before the dependent services can run. |
Prototype | BOOL EnumDependentServices( SC_HANDLE hService, DWORD dwServiceState, LPENUM_SERVICE_STATUS lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned ); |
Parameters | See below. |
Return value | See below. |
Include file | <windows.h> |
Remark | Implemented as Unicode and ANSI versions. The returned services entries are ordered in the reverse order of the start order, with group order taken into account. If you need to stop the dependent services, you can use the order of entries written to the lpServices buffer to stop the dependent services in the proper order. |
Table 5. |
Parameters
hService - [in] Handle to the service. This handle is returned by the OpenService() or CreateService() function, and it must have the SERVICE_ENUMERATE_DEPENDENTS access right.
dwServiceState - [in] Services to enumerate based on their state. This parameter can be one of the following values.
Value | Meaning |
SERVICE_ACTIVE | Enumerates services that are in the following states: SERVICE_START_PENDING, SERVICE_STOP_PENDING, SERVICE_RUNNING, SERVICE_CONTINUE_PENDING, SERVICE_PAUSE_PENDING, and SERVICE_PAUSED. |
SERVICE_INACTIVE | Enumerates services that are in the SERVICE_STOPPED state. |
SERVICE_STATE_ALL | Combines the following states: SERVICE_ACTIVE and SERVICE_INACTIVE. |
Table 6 |
lpServices - [out] Pointer to an array of ENUM_SERVICE_STATUS structures that receives the name and service status information for each dependent service in the database. The buffer must be large enough to hold the structures, plus the strings to which their members point. The order of the services in this array is the reverse of the start order of the services. In other words, the first service in the array is the one that would be started last, and the last service in the array is the one that would be started first. The maximum size of this array is 64,000 bytes. To determine the required size, specify NULL for this parameter and 0 for the cbBufSize parameter. The function will fail and GetLastError() will return ERROR_MORE_DATA. The pcbBytesNeeded parameter will receive the required size. cbBufSize - [in] Size of the buffer pointed to by the lpServices parameter, in bytes. pcbBytesNeeded - [out] Pointer to a variable that receives the number of bytes needed to store the array of service entries. The variable only receives this value if the buffer pointed to by lpServices is too small, indicated by function failure and the ERROR_MORE_DATA error; otherwise, the contents of pcbBytesNeeded are undefined. lpServicesReturned - [out] Pointer to a variable that receives the number of service entries returned. |
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, call GetLastError(). The following error codes may be set by the service control manager. Other error codes may be set by the registry functions that are called by the service control manager.
Return code | Description |
ERROR_ACCESS_DENIED | The handle does not have the SERVICE_ENUMERATE_DEPENDENTS access right. |
ERROR_INVALID_HANDLE | The specified handle is invalid. |
ERROR_INVALID_PARAMETER | A parameter that was specified is invalid. |
ERROR_MORE_DATA | The buffer pointed to by lpServices is not large enough. The function sets the variable pointed to by lpServicesReturned to the actual number of service entries stored into the buffer. The function sets the variable pointed to by pcbBytesNeeded to the number of bytes required to store all of the service entries. |
Table 7 |
HeapAlloc()
Item | Description |
Function | HeapAlloc(). |
Use | Allocates a block of memory from a heap. The allocated memory is not movable. |
Prototype | LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes); |
Parameters | See below. |
Return value | See below. |
Include file | <windows.h> |
Remark | See below. |
Table 8. |
Parameters
hHeap - [in] Handle to the heap from which the memory will be allocated. This handle is returned by the HeapCreate() or GetProcessHeap() function.
dwFlags - [in] Heap allocation control. Specifying any of these values will override the corresponding value specified when the heap was created with HeapCreate(). This parameter can be one or more of the following values.
Value | Meaning |
HEAP_GENERATE_EXCEPTIONS | The system will raise an exception to indicate a function failure, such as an out-of-memory condition, instead of returning NULL. |
HEAP_NO_SERIALIZE | Serialized access will not be used for this allocation. For more information, see Remarks. To ensure that serialized access is disabled for all calls to this function, specify HEAP_NO_SERIALIZE in the call to HeapCreate(). In this case, it is not necessary to additionally specify HEAP_NO_SERIALIZE in this function call. This value should not be specified when accessing the process heap. The system may create additional threads within the application's process, such as a CTRL+C handler, that simultaneously access the process heap. |
HEAP_ZERO_MEMORY | The allocated memory will be initialized to zero. Otherwise, the memory is not initialized to zero. |
Table 9 |
dwBytes - [in] Number of bytes to be allocated. If the heap specified by the hHeap parameter is a "non-growable" heap, dwBytes must be less than 0x7FFF8. You create a non-growable heap by calling the HeapCreate() function with a nonzero value.
Return Values
If the function succeeds, the return value is a pointer to the allocated memory block. If the function fails and you have not specified HEAP_GENERATE_EXCEPTIONS, the return value is NULL. If the function fails and you have specified HEAP_GENERATE_EXCEPTIONS, the function may generate the following exceptions.
Return code | Description |
STATUS_NO_MEMORY | The allocation attempt failed because of a lack of available memory or heap corruption. |
STATUS_ACCESS_VIOLATION | The allocation attempt failed because of heap corruption or improper function parameters. |
Table 10 |
Note: Heap corruption can lead to either exception. It depends upon the nature of the heap corruption.
If the function fails, it does not call SetLastError(). An application cannot call GetLastError() for extended error information.
Some Remarks
If HeapAlloc() succeeds, it allocates at least the amount of memory requested. To determine the actual size of the allocated block, use the HeapSize() function. To free a block of memory allocated by HeapAlloc(), use the HeapFree() function. Memory allocated by HeapAlloc() is not movable. The address returned by HeapAlloc() is valid until the memory block is freed or reallocated; the memory block does not need to be locked. Because the system cannot compact a private heap, it can become fragmented. Applications that allocate large amounts of memory in various allocation sizes can use the low-fragmentation heap to reduce heap fragmentation. Serialization ensures mutual exclusion when two or more threads attempt to simultaneously allocate or free blocks from the same heap. There is a small performance cost to serialization, but it must be used whenever multiple threads allocate and free memory from the same heap. Setting the HEAP_NO_SERIALIZE value eliminates mutual exclusion on the heap. Without serialization, two or more threads that use the same heap handle might attempt to allocate or free memory simultaneously, likely causing corruption in the heap. The HEAP_NO_SERIALIZE value can, therefore, be safely used only in the following situations:
The process has only one thread.
The process has multiple threads, but only one thread calls the heap functions for a specific heap.
The process has multiple threads, and the application provides its own mechanism for mutual exclusion to a specific heap.
Windows Me/98/95: The heap managers are designed for memory blocks smaller than four megabytes. If you expect your memory blocks to be larger than one or two megabytes, you can avoid significant performance degradation by using the VirtualAlloc() or VirtualAllocEx() function instead.
HeapFree()
Item | Description |
Function | HeapFree(). |
Use | Frees a memory block allocated from a heap by the HeapAlloc() or HeapReAlloc() function. |
Prototype | BOOL HeapFree( HANDLE hHeap, DWORD dwFlags, LPVOID lpMem); |
Parameters | See below. |
Return value | If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. An application can call GetLastError() for extended error information. |
Include file | <windows.h> |
Remark | See below. |
Table 11. |
Parameters
hHeap - [in] Handle to the heap whose memory block is to be freed. This handle is a returned by either the HeapCreate() or GetProcessHeap() function.
dwFlags - [in] Heap free options. Specifying the following value overrides the corresponding value specified in the flOptions parameter when the heap was created by using the HeapCreate() function.
Value | Meaning |
HEAP_NO_SERIALIZE | Serialized access will not be used. For more information, see Remarks section. To ensure that serialized access is disabled for all calls to this function, specify HEAP_NO_SERIALIZE in the call to HeapCreate(). In this case, it is not necessary to additionally specify HEAP_NO_SERIALIZE in this function call. Do not specify this value when accessing the process heap. The system may create additional threads within the application's process, such as a CTRL+C handler, that simultaneously access the process heap. |
Table 12 |
lpMem - [in] Pointer to the memory block to be freed. This pointer is returned by the HeapAlloc() or HeapReAlloc() function.
Some Remarks
You should not refer in any way to memory that has been freed by HeapFree(). After that memory is freed, any information that may have been in it is gone forever. If you require information, do not free memory containing the information. Function calls that return information about memory (such as HeapSize()) may not be used with freed memory, as they may return bogus data. Serialization ensures mutual exclusion when two or more threads attempt to simultaneously allocate or free blocks from the same heap. There is a small performance cost to serialization, but it must be used whenever multiple threads allocate and free memory from the same heap. Setting the HEAP_NO_SERIALIZE value eliminates mutual exclusion on the heap. Without serialization, two or more threads that use the same heap handle might attempt to allocate or free memory simultaneously, likely causing corruption in the heap. The HEAP_NO_SERIALIZE value can, therefore, be safely used only in the following situations:
The process has only one thread.
The process has multiple threads, but only one thread calls the heap functions for a specific heap.
The process has multiple threads, and the application provides its own mechanism for mutual exclusion to a specific heap.
GetProcessHeap()
Item | Description |
Function | GetProcessHeap(). |
Use | Obtains a handle to the heap of the calling process. This handle can then be used in subsequent calls to the heap functions. |
Prototype | HANDLE GetProcessHeap(void); |
Parameters | This function has no parameters. |
Return value | If the function succeeds, the return value is a handle to the calling process's heap. If the function fails, the return value is NULL. To get extended error information, call GetLastError(). |
Include file | <windows.h> |
Remark | The GetProcessHeap() function allows you to allocate memory from the process heap without having to first create a heap with the HeapCreate() function, as shown in this example:
HeapAlloc(GetProcessHeap(), 0, dwBytes);
By default, the process heap is a standard heap. To use the low-fragmentation heap, call the HeapSetInformation() function. |
Table 13. |
ControlService()
Item | Description |
Function | ControlService(). |
Use | Sends a control code to a service. |
Prototype | BOOL ControlService( SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus); |
Parameters | See below. |
Return value | See below. |
Include file | <windows.h> |
Remark | See below. |
Table 14. |
Parameters
hService - [in] Handle to the service. This handle is returned by the OpenService() or CreateService() function. The access rights required for this handle depend on the dwControl code requested.
dwControl - [in] This parameter can be one of the following control codes.
Control code | Meaning |
SERVICE_CONTROL_CONTINUE | Notifies a paused service that it should resume. The hService handle must have the SERVICE_PAUSE_CONTINUE access right. |
SERVICE_CONTROL_INTERROGATE | Notifies a service that it should report its current status information to the service control manager. The hService handle must have the SERVICE_INTERROGATE access right. |
SERVICE_CONTROL_NETBINDADD | Notifies a network service that there is a new component for binding. The hService handle must have the SERVICE_PAUSE_CONTINUE access right. However, this control code has been deprecated; use PnP functionality instead. Windows NT: This value is not supported. |
SERVICE_CONTROL_NETBINDDISABLE | Notifies a network service that one of its bindings has been disabled. The hService handle must have the SERVICE_PAUSE_CONTINUE access right. However, this control code has been deprecated; use PnP functionality instead. Windows NT: This value is not supported. |
SERVICE_CONTROL_NETBINDENABLE | Notifies a network service that a disabled binding has been enabled. The hService handle must have the SERVICE_PAUSE_CONTINUE access right. However, this control code has been deprecated; use PnP functionality instead. Windows NT: This value is not supported. |
SERVICE_CONTROL_NETBINDREMOVE | Notifies a network service that that a component for binding has been removed. The hService handle must have the SERVICE_PAUSE_CONTINUE access right. However, this control code has been deprecated; use PnP functionality instead. Windows NT: This value is not supported. |
SERVICE_CONTROL_PARAMCHANGE | Notifies a service that its startup parameters have changed. The hService handle must have the SERVICE_PAUSE_CONTINUE access right. Windows NT: This value is not supported. |
SERVICE_CONTROL_PAUSE | Notifies a service that it should pause. The hService handle must have the SERVICE_PAUSE_CONTINUE access right. |
SERVICE_CONTROL_STOP | Notifies a service that it should stop. The hService handle must have the SERVICE_STOP access right. |
Table 15 |
This value can also be a user-defined control code, as described in the following table.
Control code | Meaning |
Range 128 to 255. | The service defines the action associated with the control code. The hService handle must have the SERVICE_USER_DEFINED_CONTROL access right. |
Table 16 |
lpServiceStatus - [out] Pointer to a SERVICE_STATUS structure that receives the latest service status information. The information returned reflects the most recent status that the service reported to the service control manager. The service control manager fills in the structure only when ControlService() returns one of the following error codes: NO_ERROR, ERROR_INVALID_SERVICE_CONTROL, ERROR_SERVICE_CANNOT_ACCEPT_CTRL, or ERROR_SERVICE_NOT_ACTIVE. Otherwise, the structure is not filled in.
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, 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 are called by the service control manager.
Return code | Description |
ERROR_ACCESS_DENIED | The handle does not have the required access right. |
ERROR_DEPENDENT_SERVICES_RUNNING | The service cannot be stopped because other running services are dependent on it. |
ERROR_INVALID_HANDLE | The specified handle was not obtained using CreateService() or OpenService(), or the handle is no longer valid. |
ERROR_INVALID_PARAMETER | The requested control code is undefined. |
ERROR_INVALID_SERVICE_CONTROL | The requested control code is not valid, or it is unacceptable to the service. |
ERROR_SERVICE_CANNOT_ACCEPT_CTRL | The requested control code cannot be sent to the service because the state of the service is SERVICE_STOPPED, SERVICE_START_PENDING, or SERVICE_STOP_PENDING. |
ERROR_SERVICE_NOT_ACTIVE | The service has not been started. |
ERROR_SERVICE_REQUEST_TIMEOUT | The process for the service was started, but it did not call StartServiceCtrlDispatcher(), or the thread that called StartServiceCtrlDispatcher() may be blocked in a control handler function. |
ERROR_SHUTDOWN_IN_PROGRESS | The system is shutting down. |
Table 17 |
Some Remarks
The ControlService() function asks the Service Control Manager (SCM) to send the requested control code to the service. The SCM sends the code if the service has specified that it will accept the code, and is in a state in which a control code can be sent to it. The SCM processes service control notifications in a serial fashion, it will wait for one service to complete processing a service control notification before sending the next one. Because of this, a call to ControlService() will block for 30 seconds if any service is busy handling a control code. If the busy service still has not returned from its handler function when the timeout expires, ControlService() fails with ERROR_SERVICE_REQUEST_TIMEOUT. To stop and start a service requires a security descriptor that allows you to do so. The default security descriptor allows the LocalSystem account, and members of the Administrators and Power Users groups to stop and start services. The QueryServiceStatus() or function returns a SERVICE_STATUS structure whose dwCurrentState and dwControlsAccepted members indicate the current state and controls accepted by a running service. All running services accept the SERVICE_CONTROL_INTERROGATE control code by default. Drivers do not accept control codes other than SERVICE_CONTROL_STOP and SERVICE_CONTROL_INTERROGATE. Each service specifies the other control codes that it accepts when it calls the SetServiceStatus() function to report its status. A service should always accept these codes when it is running, no matter what it is doing. The following table shows the action of the SCM in each of the possible service states.
Service state | Stop | Other controls |
STOPPED (The service is not running.) | (c) | (c) |
STOP_PENDING (The service is stopping.) | (b) | (b) |
START_PENDING (The service is starting.) | (a) | (b) |
RUNNING (The service is running.) | (a) | (a) |
CONTINUE_PENDING (The service continue is pending.) | (a) | (a) |
PAUSE_PENDING (The service pause is pending.) | (a) | (a) |
PAUSED (The service is paused.) | (a) | (a) |
Table 18 |
Legend: | |
(a) | If the service accepts this control code, send the request to the service; otherwise, ControlService() returns zero and GetLastError() returns ERROR_INVALID_SERVICE_CONTROL. |
(b) | The service is not in a state in which a control can be sent to it, so ControlService() returns zero and GetLastError() returns ERROR_SERVICE_CANNOT_ACCEPT_CTRL. |
(c) | The service is not active, so ControlService() returns zero and GetLastError() returns ERROR_SERVICE_NOT_ACTIVE. |
----------------------------------------End Part 4/4----------------------------------------
Further reading and digging:
Microsoft Visual C++, on line MSDN.
Structure, enum, union and typedef story can be found at C enum, typedef, define etc..
For Multi bytes, Unicode characters and Localization please refer to Unicode & Multi-byte 1 (Story) and Unicode & Multi byte 2 (Implementation).
Windows data type information is in Windows data type.
Check the best selling C / C++ and Windows books at Amazon.com.