/******************************************************************************* * * 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; }