windows-nt/Source/XPSP1/NT/shell/osshell/cpls/powercfg/ups/upscommon.c
2020-09-26 16:20:57 +08:00

799 lines
24 KiB
C

/*******************************************************************************
*
* Copyright 1999 American Power Conversion, All Rights Reserved
*
* TITLE: UPSCOMMON.C
*
* VERSION: 1.0
*
* AUTHOR: SteveT
*
* DATE: 07 June, 1999
*
* DESCRIPTION: This file contains functions that are used by various different module,
* or are generic enough to be used by varoius different modules even if
* they are only being used in one place at present.
********************************************************************************/
#include "upstab.h"
#include "prsht.h"
#pragma hdrstop
// static data
///////////////////////////////////////////////////////////////////////////////
static HWND g_hUPSPage = 0; //Used in
//InitializeApplyButton and
//EnableApplyButton
static DWORD g_CurrentActiveDataState = 0; //Used in
//AddActiveDataState
//GetActiveDataState and
//SetActiveDataState
extern HINSTANCE g_hInstance; //Global instance handle of this DLL
// functions
///////////////////////////////////////////////////////////////////////////////
DWORD GetServiceStatus_Control (LPCTSTR aServiceName, LPDWORD lpStatus);
DWORD GetServiceStatus_Query (LPCTSTR aServiceName, LPDWORD lpStatus);
DWORD GetServiceStatus_Enum (LPCTSTR aServiceName, LPDWORD lpStatus);
DWORD ManageService (LPCTSTR aServiceName,
DWORD aDesiredSCAccess,
DWORD aDesiredServiceAccess,
DWORD aAction,
BOOL bWait,
DWORD aWaitStatus,
LPDWORD lpStatus);
BOOL WaitForServiceStatus (SC_HANDLE aHandle, DWORD aStatus);
DWORD LoadUPSString (DWORD aMsgID,
LPTSTR aMessageBuffer,
DWORD * aBufferSizePtr);
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// HMODULE GetUPSModuleHandle (void);
//
// Description: This function gets the HMODULE of the module that created
// the UPS tab dialog.
//
// Additional Information:
//
// Parameters: None
//
// Return Value: Returns the HMODULE of the module that created the dialog.
//
HMODULE GetUPSModuleHandle (void) {
static HMODULE hModule = NULL;
if (hModule == NULL) {
#ifdef _APC_
hModule = GetModuleHandle(UPS_EXE_FILE);
#else
hModule = g_hInstance;
#endif
}
return(hModule);
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// void InitializeApplyButton (HWND aDlgHWND);
//
// Description: This function sets the data needed to allow the
// EnableApplyButton to
//
// Additional Information:
//
// Parameters:
//
// HWND aDlgHWND :-
//
// Return Value: None
//
void InitializeApplyButton (HWND aDlgHWND) {
_ASSERT(g_hUPSPage == 0);
_ASSERT(aDlgHWND != 0);
g_hUPSPage = aDlgHWND;
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// void EnableApplyButton (void);
//
// Description: This function enables the "Apply" button on the main UPS page
//
// Additional Information:
//
// Parameters: None
//
// Return Value: None
//
void EnableApplyButton (void) {
HWND hParent = 0;
_ASSERT(g_hUPSPage != 0); //Should call InitializeApplyButton
//to initialize.
hParent = GetParent(g_hUPSPage);
PropSheet_Changed(hParent, g_hUPSPage);
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// BOOL RestartService (LPCTSTR aServiceName, BOOL bWait);
//
// Description: This function restarts the specified service
//
// Additional Information:
//
// Parameters:
//
// LPCTSTR aServiceName :- The name of the service to restart
//
// BOOL bWait :- A BOOL that specifies if the process should wait for the
// the service to fully restart. If TRUE then this process
// returns when the service has fully restarted. If FALSE
// then this process tells the service to start but does
// not wait around for it to be fully started before returning.
//
// Return Value: If the given service restarts successfully then this function
// returns TRUE, otherwise it returns FALSE.
//
BOOL RestartService (LPCTSTR aServiceName, BOOL bWait) {
StopService(aServiceName);
return(StartOffService(aServiceName, bWait));
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// BOOL StartOffService (LPCTSTR aServiceName, BOOL bWaitForService);
//
// Description: This function starts the specified service
//
// Additional Information:
//
// Parameters:
//
// LPCTSTR aServiceName :- The name of the service to start
//
// BOOL bWaitForService :- A BOOL that specifies if the process should wait
// for the the service to fully start. If TRUE then
// this process returns when the service has fully
// started. If FALSE then this process tells the
// service to start but does not wait around for it
// to be fully started before returning.
//
// Return Value: If the given service starts successfully then this function
// returns TRUE, otherwise it returns FALSE.
//
BOOL StartOffService (LPCTSTR aServiceName, BOOL bWaitForService) {
BOOL bStartedOK = FALSE;
SC_HANDLE hManager = NULL;
if ((hManager = OpenSCManager(NULL, NULL, GENERIC_READ)) != NULL) {
SC_HANDLE service_handle = NULL;
if ((service_handle = OpenService(hManager,
aServiceName,
SERVICE_START | SERVICE_INTERROGATE | SERVICE_QUERY_STATUS)) != NULL) {
SERVICE_STATUS service_status;
SetLastError(0);
ZeroMemory(&service_status, sizeof(service_status));
if ((bStartedOK = StartService(service_handle,
0,
NULL)) == TRUE) {
SetLastError(0);
if (bWaitForService == TRUE) {
bStartedOK = WaitForServiceStatus(service_handle, SERVICE_RUNNING);
}
}
else {
_ASSERT(FALSE);
}
if (CloseServiceHandle(service_handle) == FALSE) {
_ASSERT(FALSE);
//error closing service configuration manager
}
}
if (CloseServiceHandle(hManager) == FALSE) {
//error closing service configuration manager
_ASSERT(FALSE);
}
}
return(bStartedOK);
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// BOOL WaitForServiceStatus (SC_HANDLE aHandle, DWORD aStatus);
//
// Description: This function waits for the service identified by the given
// service handle to enter the given state.
//
// Additional Information:
//
// Parameters:
//
// SC_HANDLE aHandle :- A handle to an open service.
//
// DWORD aStatus :- The status to wait for. The allows value for this
// parameter are defined by the dwCurrentState member of the
// structure.
//
// Return Value:
//
BOOL WaitForServiceStatus (SC_HANDLE aHandle, DWORD aStatus) {
SERVICE_STATUS service_status;
DWORD dwOldCheck = 0;
BOOL bStatusSet = FALSE;
ZeroMemory(&service_status, sizeof(service_status));
bStatusSet = QueryServiceStatus(aHandle, &service_status);
if (bStatusSet == FALSE) {
return(bStatusSet);
}
while (service_status.dwCurrentState != aStatus) {
dwOldCheck = service_status.dwCheckPoint;
Sleep(service_status.dwWaitHint);
if ((bStatusSet = QueryServiceStatus(aHandle, &service_status)) == FALSE) {
break;
}
if (dwOldCheck >= service_status.dwCheckPoint) {
break;
}
}//end while
if (service_status.dwCurrentState == aStatus) {
bStatusSet = TRUE;
}
else {
TCHAR errMessageBuffer[MAX_PATH] = TEXT("");
DWORD errMessageBufferSize = MAX_PATH;
bStatusSet = FALSE;
//Must load the error message from "netmsg.dll"
if ((LoadUPSString(service_status.dwWin32ExitCode,
errMessageBuffer,
&errMessageBufferSize) == ERROR_SUCCESS) &&
(*errMessageBuffer != TEXT('\0'))) {
MessageBox(NULL, errMessageBuffer, NULL, MB_OK | MB_ICONEXCLAMATION);
}
}
return(bStatusSet);
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// DWORD LoadUPSString (DWORD aMsgID,
// LPTSTR aMessageBuffer,
// DWORD * aBufferSizePtr);
//
// Description: This function load the string resource identified by aMsgID
// into the buffer identified by aMessageBuffer
//
// Additional Information:
//
// Parameters:
//
// DWORD aMsgID :- ID of string resource to load
//
// LPTSTR aMessageBuffer :- Pointer to a buffer where the string is to be
// copied.
//
// DWORD * aBufferSizePtr :- The size of the buffer.
//
// Return Value: Returns a Win32 error code. ERROR_SUCCESS on success.
//
DWORD LoadUPSString (DWORD aMsgID,
LPTSTR aMessageBuffer,
DWORD * aBufferSizePtr) {
LPTSTR lpBuf = NULL; // Will Hold text of the message (allocated by FormatMessage
DWORD errStatus = ERROR_SUCCESS;
DWORD numChars = 0;
HMODULE hNetMsg = LoadLibrary(TEXT("netmsg.dll"));
if (hNetMsg != NULL) {
if (numChars = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER,
(LPCVOID) hNetMsg,
aMsgID,
0,
(LPTSTR) &lpBuf,
*aBufferSizePtr,
(va_list *)0) == 0) {
*aBufferSizePtr = 0;
*aMessageBuffer = TEXT('\0');
}
else {
if (aBufferSizePtr != NULL) {
if (numChars < *aBufferSizePtr) {
//the given buffer is big enough to hold the string
if (aMessageBuffer != NULL) {
_tcscpy(aMessageBuffer, lpBuf);
}
}
*aBufferSizePtr = numChars;
}
LocalFree(lpBuf);
}
FreeLibrary(hNetMsg);
}
return(errStatus);
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// void StopService (LPCTSTR aServiceName);
//
// Description: This function stops the service named.
//
// Additional Information:
//
// Parameters:
//
// LPCTSTR aServiceName :- The name of the service
//
// Return Value: None
//
void StopService (LPCTSTR aServiceName) {
DWORD dwStatus = SERVICE_STOPPED;
DWORD dwError = ERROR_SUCCESS;
dwError = ManageService(aServiceName,
GENERIC_READ,
SERVICE_STOP | SERVICE_INTERROGATE | SERVICE_QUERY_STATUS,
SERVICE_CONTROL_STOP,
TRUE,
SERVICE_STOPPED,
&dwStatus);
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// BOOL IsServiceRunning (LPCTSTR aServiceName);
//
// Description: This function checks if the service named is running.
//
// Additional Information:
//
// Parameters:
//
// LPCTSTR aServiceName :- The name of the service
//
// Return Value: TRUE if the service is running, FALSE otherwise.
//
BOOL IsServiceRunning (LPCTSTR aServiceName)
{
DWORD dwStatus = SERVICE_STOPPED;
// There are three methods of retrieving the service status
// 1. Interrogate the service using ControlService() - most accurate
// 2. Query the service using QueryServiceStatus() - most efficient
// 3. Query the service using EnumServicesStatus() - most accessible
if (GetServiceStatus_Control(aServiceName, &dwStatus) != ERROR_SUCCESS)
{
if (GetServiceStatus_Query(aServiceName, &dwStatus) != ERROR_SUCCESS)
{
GetServiceStatus_Enum(aServiceName, &dwStatus);
}
}
return(SERVICE_RUNNING == dwStatus);
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// DWORD GetServiceStatus_Control (LPCTSTR aServiceName, LPDWORD lpStatus);
//
// Description: This function returns the status of the service named
// using the Win32 API call ControlService(). This is the
// most accurate way to retrieve the service staus.
//
// Parameters:
//
// IN
// LPCTSTR aServiceName :- The name of the service
//
// OUT
// LPDWORD lpStatus :- The service status
//
// Return Value: Returns a Win32 error code. ERROR_SUCCESS on success.
//
DWORD GetServiceStatus_Control (LPCTSTR aServiceName, LPDWORD lpStatus)
{
DWORD dwError = ERROR_SUCCESS;
*lpStatus = SERVICE_STOPPED;
dwError = ManageService(aServiceName,
SC_MANAGER_ENUMERATE_SERVICE,
SERVICE_INTERROGATE | SERVICE_QUERY_STATUS,
SERVICE_CONTROL_INTERROGATE,
FALSE,
0,
lpStatus);
return dwError;
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// DWORD GetServiceStatus_Query (LPCTSTR aServiceName, LPDWORD lpStatus);
//
// Description: This function returns the status of the service named.
// using the Win32 API call QueryServiceStatus(). This is the
// most efficient way to retrieve the service staus.
//
// Parameters:
//
// IN
// LPCTSTR aServiceName :- The name of the service
//
// OUT
// LPDWORD lpStatus :- The service status
//
// Return Value: Returns a Win32 error code. ERROR_SUCCESS on success.
//
DWORD GetServiceStatus_Query (LPCTSTR aServiceName, LPDWORD lpStatus)
{
DWORD dwError = ERROR_SUCCESS;
SC_HANDLE hManager = NULL;
*lpStatus = SERVICE_STOPPED;
if (NULL != (hManager = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE)))
{
SC_HANDLE service_handle = NULL;
if (NULL != (service_handle = OpenService(hManager,
aServiceName,
SERVICE_QUERY_STATUS)))
{
SERVICE_STATUS service_status;
ZeroMemory(&service_status, sizeof(service_status));
if( QueryServiceStatus(service_handle, &service_status) != 0 )
{
*lpStatus = service_status.dwCurrentState;
}
else
{
dwError = GetLastError();
}
if (CloseServiceHandle(service_handle) == FALSE)
{
_ASSERT(FALSE);
//error closing service configuration manager
}
}
else
{
dwError = GetLastError();
}
if (CloseServiceHandle(hManager) == FALSE)
{
//error closing service configuration manager
_ASSERT(FALSE);
}
}
else
{
dwError = GetLastError();
}
return dwError;
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// DWORD GetServiceStatus_Enum (LPCTSTR aServiceName, LPDWORD lpStatus);
//
// Description: This function returns the status of the service named.
// using the Win32 API call EnumServicesStatus(). This call
// requires the mimimum access privileges but is the most
// inefficient accurate way to retrieve the service staus.
//
// Parameters:
//
// IN
// LPCTSTR aServiceName :- The name of the service
//
// OUT
// LPDWORD lpStatus :- The service status
//
// Return Value: Returns a Win32 error code. ERROR_SUCCESS on success.
//
DWORD GetServiceStatus_Enum (LPCTSTR aServiceName, LPDWORD lpStatus)
{
DWORD dwError = ERROR_SUCCESS;
SC_HANDLE hManager;
_ASSERT( NULL != lpStatus );
*lpStatus = SERVICE_STOPPED;
hManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT );
if ( NULL != hManager )
{
SC_HANDLE hService = OpenService( hManager, aServiceName, SERVICE_QUERY_STATUS );
if ( NULL != hService )
{
SERVICE_STATUS ss;
BOOL bRet = QueryServiceStatus( hService, &ss );
if ( bRet )
{
*lpStatus = ss.dwCurrentState;
}
else
{
dwError = GetLastError( );
}
CloseServiceHandle( hService );
// what do you do if this fails?
}
else
{
dwError = GetLastError( );
}
CloseServiceHandle( hManager );
// what do you do if this fails?
}
else
{
dwError = GetLastError( );
}
return dwError;
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// DWORD ManageService (LPCTSTR aServiceName,
// DWORD aDesiredSCAccess,
// DWORD aDesiredServiceAccess,
// DWORD aAction,
// BOOL bWait,
// DWORD aWaitStatus
// LPDWORD lpStatus);
//
// Description: This function opens the service named and performs the
// specified control request on the given service. The
// function optionally waits on the service to enter the
// specified status.
//
// Additional Information:
//
// Parameters:
//
// LPCTSTR aServiceName :- The name of the service
//
// DWORD aDesiredSCAccess :- The access to use to open the service control
// manager.
//
// DWORD aDesiredServiceAccess :- The access to use to open the service.
//
// DWORD aAction :- Specifies the requested control code.
//
// BOOL bWait :- TRUE specifies that this process should wait for the service
// to reach the state identified by aWaitStatus.
//
// DWORD aWaitStatus :- The service state to wait for.
//
// OUT
// LPDWORD lpStatus :- The service status
//
// Return Value: Returns a Win32 error code. ERROR_SUCCESS on success.
//
DWORD ManageService (LPCTSTR aServiceName,
DWORD aDesiredSCAccess,
DWORD aDesiredServiceAccess,
DWORD aAction,
BOOL bWait,
DWORD aWaitStatus,
LPDWORD lpStatus)
{
DWORD dwError = ERROR_SUCCESS;
SC_HANDLE hManager = NULL;
*lpStatus = SERVICE_STOPPED;
if ((hManager = OpenSCManager(NULL, NULL, aDesiredSCAccess)) != NULL) {
SC_HANDLE service_handle = NULL;
if ((service_handle = OpenService(hManager,
aServiceName,
aDesiredServiceAccess)) != NULL) {
SERVICE_STATUS service_status;
ZeroMemory(&service_status, sizeof(service_status));
if (ControlService(service_handle,
aAction,
&service_status) == TRUE) {
//OK we should now know the current state
if (bWait == TRUE) {
if (WaitForServiceStatus(service_handle, aWaitStatus) == TRUE) {
*lpStatus = aWaitStatus;
}
else {
dwError = GetServiceStatus_Enum(aServiceName,lpStatus);
}
}
else {
*lpStatus = service_status.dwCurrentState;
}
}
else {
dwError = GetLastError();
}
if (CloseServiceHandle(service_handle) == FALSE) {
_ASSERT(FALSE);
//error closing service configuration manager
}
}
else {
dwError = GetLastError();
}
if (CloseServiceHandle(hManager) == FALSE) {
//error closing service configuration manager
_ASSERT(FALSE);
}
}
else
{
dwError = GetLastError();
}
return(dwError);
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// void ConfigureService (BOOL aSetToAutoStartBool);
//
// Description: This function sets the UPS service configuration to either
// automatic or manual.
//
// Additional Information:
//
// Parameters:
//
// BOOL aSetToAutoStartBool :- TRUE for automatic. FALSE for manual.
//
// Return Value: None
//
void ConfigureService (BOOL aSetToAutoStartBool) {
SC_HANDLE hSCM = 0;
if ((hSCM = OpenSCManager(NULL, NULL, GENERIC_READ | GENERIC_EXECUTE)) != NULL) {
SC_LOCK hLock = 0;
if ((hLock = LockServiceDatabase(hSCM)) != NULL) {
SC_HANDLE hService = 0;
if ((hService = OpenService(hSCM, UPS_SERVICE_NAME, SERVICE_CHANGE_CONFIG)) != NULL) {
DWORD dwStartType = 0;
dwStartType = (aSetToAutoStartBool == TRUE) ? SERVICE_AUTO_START : SERVICE_DEMAND_START;
ChangeServiceConfig(hService,
SERVICE_NO_CHANGE,
dwStartType,
SERVICE_NO_CHANGE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
CloseServiceHandle(hService);
}//end Open
UnlockServiceDatabase(hLock);
}//end Lock
CloseServiceHandle(hSCM);
}//end OpenSCM
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// void AddActiveDataState (DWORD aBitToSet);
//
// Description: This function adds the given bit to current active data state.
// The active data state is the state of the current UPS data set.
// The UPS data set can include SERVICE_DATA_CHANGE and
// CONFIG_DATA_CHANGE which signify that the service data like UPS
// vendor, model name, etc, has changed. SERVICE_DATA_CHANGE is
// for data the require the service to be restarted when changed.
// CONFIG_DATA_CHANGE is for data that has changed but that does
// not require a service restart.
//
// Additional Information:
//
// Parameters:
//
// DWORD aBitToSet :- The bit to set. Can be either SERVICE_DATA_CHANGE or
// CONFIG_DATA_CHANGE.
//
// Return Value: None
//
void AddActiveDataState (DWORD aBitToSet) {
g_CurrentActiveDataState |= aBitToSet;
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// DWORD GetActiveDataState (void);
//
// Description: This function returns the current value of the active data
// set. This value should be & with SERVICE_DATA_CHANGE and
// CONFIG_DATA_CHANGE to determine the current active data state.
//
// Additional Information:
//
// Parameters: None
//
// Return Value: Returns the current active data state.
//
DWORD GetActiveDataState (void) {
return(g_CurrentActiveDataState);
}
//////////////////////////////////////////////////////////////////////////_/_//
//////////////////////////////////////////////////////////////////////////_/_//
// void SetActiveDataState (DWORD aNewValue);
//
// Description: This function replaces the current value of the active data
// state.
//
// Additional Information:
//
// Parameters:
//
// DWORD aNewValue :- The new value for the active data state.
//
// Return Value: None
//
void SetActiveDataState (DWORD aNewValue) {
g_CurrentActiveDataState = aNewValue;
}