NT Service Question `
- From: "Natalia DeBow" <natalia.debow@xxxxxxxxxx>
- Date: Mon, 12 Nov 2007 18:48:09 -0800
Hello there,
I have a question with trying to programmatically stop the RSM service.
The problem that I am experiencing is that I am getting a timeout error
while trying to stop RSM service at the system startup. The logic to stop
the RSM service is triggered by another NT service. In order to
programmatically stop the RSM service, I used the sample code available on
MSDN, however, I'm getting a timeout error and strangely enough right after
the error message was posted, the SCM posts a message notifying me that the
RSM was stopped. So, in the end, the RSM was indeed stopped.
Here is the code that performs the stopping of the RSM service:
BOOL StopRSMService(
OUT DWORD &WNTErrorCode // only useful if FALSE returned
)
{
const TCHAR FUNCNAME[] = "StopRSMService";
BOOL fSuccess = TRUE;
WNTErrorCode = ERROR_SUCCESS;
SERVICE_STATUS_PROCESS ssp;
DWORD dwStartCheckPoint = 0;
DWORD dwStartTickCount = 0;
DWORD dwWaitTime = 0;
DWORD dwBytesNeeded = 0;
__try
{
// Open the Service Control Manager database
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS // full access rights
);
if (NULL == schSCManager)
{
// Failed to open the SCM database
WNTErrorCode = GetLastError();
fSuccess = FALSE;
XDBG_LOG1(DFI, FUNCNAME, "OpenSCManager failed with WNTError code: %lu.",
WNTErrorCode);
__leave;
}
// Open the RSM service
schService = OpenService(
schSCManager, // SCM database
RSM_SERVICE_NAME, // name of service
SERVICE_STOP | // desired access
SERVICE_QUERY_STATUS |
SERVICE_ENUMERATE_DEPENDENTS
);
if (NULL == schService)
{
// Failed to open the RSM service
WNTErrorCode = GetLastError();
fSuccess = FALSE;
XDBG_LOG1(DFI, FUNCNAME, "OpenService failed with WNTError code: %lu.",
WNTErrorCode);
__leave;
}
// A Windows Service can be in one of the following states:
// SERVICE_STOPPED = 0x00000001
// SERVICE_START_PENDING = 0x00000002
// SERVICE_STOP_PENDING = 0x00000003
// SERVICE_RUNNING = 0x00000004
// SERVICE_CONTINUE_PENDING = 0x00000005
// SERVICE_PAUSE_PENDING = 0x00000006
// SERVICE_PAUSED = 0x00000007
// Make sure the service is not already stopped
if (!QueryServiceStatusEx(
schService, // handle to service
SC_STATUS_PROCESS_INFO, // info level
(LPBYTE)&ssp, // pointer to buffer that receives the status
structure
sizeof(SERVICE_STATUS_PROCESS), // size of the status structure in bytes
&dwBytesNeeded) // size in bytes needed, if buffer's too small
)
{
// Failed to query the RSM status
WNTErrorCode = GetLastError();
fSuccess = FALSE;
XDBG_LOG1(DFI, FUNCNAME, "QueryServiceStatusEx failed with WNTError code:
%lu.", WNTErrorCode);
__leave;
}
// If the RSM service is already in the stopped state, we are done.
if (ssp.dwCurrentState == SERVICE_STOPPED)
{
XDBG_LOG0(DFI, FUNCNAME, "RSM service is already in the stopped state.");
__leave;
}
// If the RSM service is pending to stop, wait for it to get into the
stopped state or time out.
if (ssp.dwCurrentState == SERVICE_STOP_PENDING)
{
// Save the tick count and initial checkpoint
dwStartTickCount = GetTickCount();
dwStartCheckPoint = ssp.dwCheckPoint;
// If a stop is pending, wait for it
while (ssp.dwCurrentState == SERVICE_STOP_PENDING)
{
XDBG_LOG0(DFI, FUNCNAME, "RSM service is in the stop pending state.");
// Do not wait longer than the wait hint. A reasonable interval is
one-tenth the wait hint,
// but no less than 1 second and no more than 10 seconds
dwWaitTime = ssp.dwWaitHint / SERVICE_WAIT_TIME_RATIO;
if (dwWaitTime < SERVICE_WAIT_TIME_MIN) // 1000 milliseconds
dwWaitTime = SERVICE_WAIT_TIME_MIN;
else if (dwWaitTime > SERVICE_WAIT_TIME_MAX) // 10000 milliseconds
dwWaitTime = SERVICE_WAIT_TIME_MAX;
Sleep(dwWaitTime);
if (!QueryServiceStatusEx(
schService, // handle to service
SC_STATUS_PROCESS_INFO, // info level
(LPBYTE)&ssp, // pointer to buffer that receives the status
structure
sizeof(SERVICE_STATUS_PROCESS), // size of the status structure in
bytes
&dwBytesNeeded) // size in bytes needed, if buffer's too small
)
{
// Failed to query the RSM status
WNTErrorCode = GetLastError();
fSuccess = FALSE;
XDBG_LOG1(DFI, FUNCNAME, "QueryServiceStatusEx failed with WNTError
code: %lu.", WNTErrorCode);
__leave;
}
// Determine if the service has been stopped
if (ssp.dwCurrentState == SERVICE_STOPPED)
{
XDBG_LOG0(DFI, FUNCNAME, "RSM service was stopped successfully.");
__leave;
}
if (ssp.dwCheckPoint > dwStartCheckPoint)
{
// The service is making progress
dwStartTickCount = GetTickCount();
dwStartCheckPoint = ssp.dwCheckPoint;
}
else
{
if (GetTickCount() - dwStartTickCount > ssp.dwWaitHint)
{
// No progress has been made within the wait hint
// Time out error
SetLastError(ERROR_TIMEOUT);
WNTErrorCode = GetLastError();
fSuccess = FALSE;
XDBG_LOG2(DFI, FUNCNAME, "Wait timed out after %lu miliseconds while
RSM service stop was pending. WNTError code: %lu", ssp.dwWaitHint,
WNTErrorCode);
__leave;
}
}
} // end of while loop
} // end of if statement
// Check if dependent service(s) need to be stopped first
if (!StopRSMDependentServices(
WNTErrorCode)
)
{
fSuccess = FALSE;
XDBG_LOG1(DFI, FUNCNAME, "A call to stop RSM dependent services failed.
WNTError code: %lu", WNTErrorCode);
__leave;
}
// Send a stop code to the service
// This API returns an error code if the service is not either in the
running or paused state.
if (!ControlService(
schService, // handle to service
SERVICE_CONTROL_STOP, // service control flag
(LPSERVICE_STATUS) &ssp)// pointer to service status structure
)
{
// Failed to send the stop code to the RSM service
WNTErrorCode = GetLastError();
fSuccess = FALSE;
XDBG_LOG1(DFI, FUNCNAME, "ControlService failed with WNTError code:
%lu.", WNTErrorCode);
__leave;
}
// Save the tick count and initial checkpoint
dwStartTickCount = GetTickCount();
dwStartCheckPoint = ssp.dwCheckPoint;
// Wait for the service to stop or time out
while (ssp.dwCurrentState != SERVICE_STOPPED)
{
// Do not wait longer than the wait hint. A reasonable interval is
one-tenth the wait hint,
// but no less than 1 second and no more than 10 seconds
dwWaitTime = ssp.dwWaitHint / SERVICE_WAIT_TIME_RATIO;
if (dwWaitTime < SERVICE_WAIT_TIME_MIN) // 1000 milliseconds
dwWaitTime = SERVICE_WAIT_TIME_MIN;
else if (dwWaitTime > SERVICE_WAIT_TIME_MAX) // 10000 milliseconds
dwWaitTime = SERVICE_WAIT_TIME_MAX;
Sleep(dwWaitTime);
if (!QueryServiceStatusEx(
schService, // handle to service
SC_STATUS_PROCESS_INFO, // info level
(LPBYTE)&ssp, // pointer to buffer that receives the status
structure
sizeof(SERVICE_STATUS_PROCESS), // size of the status structure in
bytes
&dwBytesNeeded) // size in bytes needed, if buffer's too small
)
{
// Failed to query the RSM status
WNTErrorCode = GetLastError();
fSuccess = FALSE;
XDBG_LOG1(DFI, FUNCNAME, "QueryServiceStatusEx failed with WNTError
code: %lu.", WNTErrorCode);
__leave;
}
if (ssp.dwCurrentState == SERVICE_STOPPED)
break;
if (ssp.dwCheckPoint > dwStartCheckPoint)
{
// The service is making progress
dwStartTickCount = GetTickCount();
dwStartCheckPoint = ssp.dwCheckPoint;
}
else
{
DWORD temp = GetTickCount();
if ((temp - dwStartTickCount) > ssp.dwWaitHint)
{
// No progress has been made within the wait hint
// Time out error
SetLastError(ERROR_TIMEOUT);
WNTErrorCode = GetLastError();
fSuccess = FALSE;
XDBG_LOG2(DFI, FUNCNAME, "Wait timed out after %lu miliseconds while
RSM service stop was pending. WNTError code: %lu", ssp.dwWaitHint,
WNTErrorCode);
__leave;
}
}
} // end of while
XDBG_LOG0(DFI, FUNCNAME, "RSM service successfully stopped.");
} // end of try block
__finally
{
// Close all open handles
if (schService)
CloseServiceHandle(schService);
if (schSCManager)
CloseServiceHandle(schSCManager);
}
return fSuccess;
}
From my tracing, it looks like, the very last while loop is being executedand the error being reported back states that the Wait timed out after 0
miliseconds while RSM service stop was pending. WNErrorCode is 1460.
From the error message, it looks like the ssp.dwWaitHint value returned bythe QueryServiceStatusEx API was 0, however, the RSM service was still in
the PENDING state.
Is there an explanation as to why would the QueryServiceStatusEx return
ssp.dwWaitHint being set to 0 while on the first iteration of the while loop
this value was 120,000 miliseconds? When would this value change and under
what condition would it be reset to 0 by the QueryServiceStatusEx API?
Thanks,
Natalia
.
- Prev by Date: Re: a problem for Creating installation files for OLE Server App.
- Next by Date: WinWord.exe can not exit after automation in VB.
- Previous by thread: Re: Encrypted SummaryInformation transfer from NTFS to FAT
- Next by thread: WinWord.exe can not exit after automation in VB.
- Index(es):