2025-11-27 16:46:48 +09:00

780 lines
22 KiB
C++

// =============================================================================
// Class Implementation : COXService
// =============================================================================
//
// Source file : OXService.cpp
// Version: 9.3
// This software along with its related components, documentation and files ("The Libraries")
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office. For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "OXService.h"
#include "UTBStrOp.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// Data members -------------------------------------------------------------
// protected:
static const TCHAR szBar[] = _T("|");
const TCHAR COXService::m_cNull = _T('\0');
const TCHAR COXService::m_cBar = _T('|');
const LPCTSTR COXService::m_pszBar = szBar;
SC_HANDLE COXService::c_hSCM = NULL; // handle of the service manager
SC_LOCK COXService::c_Sclock = NULL; // handle of the service lock
DWORD COXService::c_dwSCMAccess = 0; // last access when openning service manager
// SC_HANDLE m_hSC; // handle of the service
// DWORD m_dwErrCode; // last error code
// CString m_sKeyName; // current service's key name
// Member functions ---------------------------------------------------------
COXService::COXService(LPCTSTR pszKeyName /* = NULL */)
{
m_hSC = NULL;
m_dwErrCode = 0;
if (pszKeyName)
m_sKeyName = pszKeyName;
}
COXService::COXService(const COXService& service)
{
m_hSC = NULL;
m_dwErrCode = 0;
m_sKeyName = service.m_sKeyName;
}
COXService::~COXService()
{
Close();
}
COXService& COXService::operator=(const COXService& service)
{
if(this==&service)
return *this;
m_hSC = NULL;
m_dwErrCode = 0;
m_sKeyName = service.m_sKeyName;
return *this;
}
DWORD COXService::GetLastError() const
{
return m_dwErrCode;
}
void COXService::Empty()
{
Close();
ASSERT(m_hSC == NULL);
m_dwErrCode = 0;
m_sKeyName.Empty();
}
BOOL COXService::IsEmpty() const
{
return m_sKeyName.IsEmpty();
}
CString COXService::GetKeyName() const
{
return m_sKeyName;
}
void COXService::SetKeyName(LPCTSTR pszKeyName)
{
if (!IsEmpty())
{
TRACE0("COXService::SetKeyName(): service was not empty.\r\n");
Empty();
}
m_sKeyName = pszKeyName;
}
SC_HANDLE COXService::GetHandle()
{
if (m_hSC == NULL)
Open();
return m_hSC;
}
BOOL COXService::Open(DWORD dwDesiredAccess /* = SERVICE_ALL_ACCESS */,
LPCTSTR pszKeyName /* = NULL */)
{
if (m_hSC != NULL && !Close())
return FALSE;
if (pszKeyName)
m_sKeyName = pszKeyName;
if (PrepareSCManager() && SetErrCode((m_hSC = ::OpenService(c_hSCM,
m_sKeyName, dwDesiredAccess)) != NULL))
{
TRACE1("COXService::Open(): service '%s' opened.\r\n", m_sKeyName);
return TRUE;
}
return FALSE;
}
BOOL COXService::Create(LPCTSTR pszBinaryPathName,
LPCTSTR pszDisplayName,
LPCTSTR pszKeyName /* = NULL */,
DWORD dwDesiredAccess /* = SERVICE_ALL_ACCESS */,
DWORD dwServiceType /* = SERVICE_WIN32_OWN_PROCESS */,
DWORD dwStartType /* = SERVICE_DEMAND_START */,
DWORD dwErrorControl /* = SERVICE_ERROR_NORMAL */,
LPCTSTR pszLoadOrderGroup /* = NULL */,
LPDWORD pdwTagId /* = NULL */,
LPCTSTR pszDependencies /* = NULL */,
LPCTSTR pszServiceStartName /* = NULL */,
LPCTSTR pszPassword /* = NULL */)
{
if (m_hSC != NULL && !Close())
return FALSE;
if (pszKeyName)
m_sKeyName = pszKeyName;
if (PrepareSCManager() &&
SetErrCode((m_hSC = ::CreateService(c_hSCM, m_sKeyName,
pszDisplayName, dwDesiredAccess, dwServiceType, dwStartType,
dwErrorControl, pszBinaryPathName, pszLoadOrderGroup, pdwTagId,
pszDependencies, pszServiceStartName, pszPassword)) != NULL))
{
TRACE1("COXService::Create(): service '%s' created.\r\n", m_sKeyName);
return TRUE;
}
return FALSE;
}
BOOL COXService::Close()
{
if (m_hSC == NULL)
return TRUE;
if (SetErrCode(::CloseServiceHandle(m_hSC)))
{
m_hSC = NULL;
TRACE1("COXService::Close(): service '%s' closed.\r\n", m_sKeyName);
return TRUE;
}
return FALSE;
}
BOOL COXService::Delete()
{
return PrepareSCHandle(DELETE) && SetErrCode(::DeleteService(m_hSC));
}
BOOL COXService::Start(DWORD dwNumServiceArgs /* = 0 */,
LPCTSTR* rgpszServiceArgVectors /* = NULL */)
{
return PrepareSCHandle(SERVICE_START) &&
SetErrCode(::StartService(m_hSC, dwNumServiceArgs,
rgpszServiceArgVectors));
}
BOOL COXService::Pause()
{
SERVICE_STATUS srvStatus;
return PrepareSCHandle(SERVICE_PAUSE_CONTINUE) &&
SetErrCode(::ControlService(m_hSC, SERVICE_CONTROL_PAUSE, &srvStatus));
}
BOOL COXService::Continue()
{
SERVICE_STATUS srvStatus;
return PrepareSCHandle(SERVICE_PAUSE_CONTINUE) &&
SetErrCode(::ControlService(m_hSC, SERVICE_CONTROL_CONTINUE, &srvStatus));
}
BOOL COXService::Stop()
{
SERVICE_STATUS srvStatus;
return PrepareSCHandle(SERVICE_STOP) &&
SetErrCode(::ControlService(m_hSC, SERVICE_CONTROL_STOP, &srvStatus));
}
BOOL COXService::Control(DWORD dwControl,
LPSERVICE_STATUS pszServiceStatus /* = NULL */)
{
DWORD dwMinimumAccess;
switch (dwControl)
{
case SERVICE_CONTROL_STOP:
dwMinimumAccess = SERVICE_STOP;
break;
case SERVICE_CONTROL_PAUSE:
case SERVICE_CONTROL_CONTINUE:
dwMinimumAccess = SERVICE_PAUSE_CONTINUE;
break;
case SERVICE_CONTROL_INTERROGATE:
dwMinimumAccess = SERVICE_INTERROGATE;
break;
case SERVICE_CONTROL_SHUTDOWN:
return FALSE;
default:
if (dwControl >= 128 && dwControl <= 255)
dwMinimumAccess = SERVICE_USER_DEFINED_CONTROL;
else
dwMinimumAccess = SERVICE_ALL_ACCESS;
}
// We noticed that if ::ControlService is called with an invalid controlcode
// for that service, it tries to fill the SERVICE_STATUS structure parameter.
// If this parameter is NULL, two exceptions are thrown and the true errorcode
// ERROR_INVALID_SERVICE_CONTROL is never seen. So even if the user isn't
// interested in the SERVICE_STATUS structure, we have to supply it.
if (pszServiceStatus == NULL)
{
SERVICE_STATUS srvStatus;
return PrepareSCHandle(dwMinimumAccess) &&
SetErrCode(::ControlService(m_hSC, dwControl, &srvStatus));
}
else
return PrepareSCHandle(dwMinimumAccess) &&
SetErrCode(::ControlService(m_hSC, dwControl, pszServiceStatus));
}
/////////////////////////////////////////////////////////////////////////////
// BOOL ChangeServiceConfig(SC_HANDLE hService,
// DWORD dwServiceType,
// DWORD dwStartType,
// DWORD dwErrorControl,
// LPCTSTR lpBinaryPathName,
// LPCTSTR lpLoadOrderGroup,
// LPDWORD lpdwTagId,
// LPCTSTR lpDependencies,
// LPCTSTR lpServiceStartName,
// LPCTSTR lpPassword,
// LPCTSTR lpDisplayName)
BOOL COXService::ChangeConfig(LPCTSTR pszDisplayName /* = NULL */,
DWORD dwServiceType /* = SERVICE_NO_CHANGE */,
DWORD dwStartType /* = SERVICE_NO_CHANGE */,
DWORD dwErrorControl /* = SERVICE_NO_CHANGE */,
LPCTSTR pszBinaryPathName /* = NULL */,
LPCTSTR pszLoadOrderGroup /* = NULL */,
LPDWORD pdwTagId /* = NULL */,
LPCTSTR pszDependencies /* = NULL */,
LPCTSTR pszServiceStartName /* = NULL */,
LPCTSTR pszPassword /* = NULL */)
{
return PrepareSCHandle(SERVICE_CHANGE_CONFIG) &&
SetErrCode(::ChangeServiceConfig(m_hSC,
dwServiceType, dwStartType, dwErrorControl,
pszBinaryPathName, pszLoadOrderGroup, pdwTagId, pszDependencies,
pszServiceStartName, pszPassword, pszDisplayName));
}
BOOL COXService::ChangeDisplayName(LPCTSTR pszDisplayName)
{
return ChangeConfig(pszDisplayName);
}
BOOL COXService::ChangeServiceType(DWORD dwServiceType)
{
return ChangeConfig(NULL, dwServiceType);
}
BOOL COXService::ChangeStartType(DWORD dwStartType)
{
return ChangeConfig(NULL, SERVICE_NO_CHANGE, dwStartType);
}
BOOL COXService::ChangeErrorControl(DWORD dwErrorControl)
{
return ChangeConfig(NULL, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
dwErrorControl);
}
BOOL COXService::ChangeBinaryPathName(LPCTSTR pszBinaryPathName)
{
return ChangeConfig(NULL, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
SERVICE_NO_CHANGE, pszBinaryPathName);
}
BOOL COXService::ChangeLoadOrderGroup(LPCTSTR pszLoadOrderGroup)
{
return ChangeConfig(NULL, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
SERVICE_NO_CHANGE, NULL, pszLoadOrderGroup);
}
BOOL COXService::ChangeTagId(DWORD dwTagId)
{
return ChangeConfig(NULL, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
SERVICE_NO_CHANGE, NULL, NULL, &dwTagId);
}
BOOL COXService::ChangeDependencies(LPCTSTR pszDependencies)
{
CString sDependencies = pszDependencies;
int nMinBufLength = sDependencies.GetLength() + 1;
BarToNullSeparator(sDependencies.GetBuffer(nMinBufLength));
return ChangeConfig(NULL, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
SERVICE_NO_CHANGE, NULL, NULL, NULL, sDependencies);
}
BOOL COXService::ChangeStartName(LPCTSTR pszServiceStartName,
LPCTSTR pszPassword /* = NULL */)
{
return ChangeConfig(NULL, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL,
pszServiceStartName, pszPassword);
}
/////////////////////////////////////////////////////////////////////////////
// BOOL QueryServiceConfig( SC_HANDLE hService,
// LPQUERY_SERVICE_CONFIG lpServiceConfig,
// DWORD cbBufSize,
// LPDWORD pcbBytesNeeded)
// typedef struct _QUERY_SERVICE_CONFIG { // qsc
// DWORD dwServiceType;
// DWORD dwStartType;
// DWORD dwErrorControl;
// LPTSTR lpBinaryPathName;
// LPTSTR lpLoadOrderGroup;
// DWORD dwTagId;
// LPTSTR lpDependencies;
// LPTSTR lpServiceStartName;
// LPTSTR lpDisplayName;
// } QUERY_SERVICE_CONFIG, LPQUERY_SERVICE_CONFIG;
BOOL COXService::QueryConfig(LPQUERY_SERVICE_CONFIG lpServiceConfig,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
return PrepareSCHandle(SERVICE_QUERY_CONFIG) &&
SetErrCode(::QueryServiceConfig(m_hSC, lpServiceConfig,
cbBufSize, pcbBytesNeeded));
}
#define OXSERVICE_QSC_BINARYPATHNAME 1
#define OXSERVICE_QSC_LOADORDERGROUP 2
#define OXSERVICE_QSC_DEPENDENCIES 3
#define OXSERVICE_QSC_SERVICESTARTNAME 4
#define OXSERVICE_QSC_DISPLAYNAME 5
#define OXSERVICE_QSC_SERVICETYPE 6
#define OXSERVICE_QSC_STARTTYPE 7
#define OXSERVICE_QSC_ERRORCONTROL 8
#define OXSERVICE_QSC_TAGID 9
CString COXService::QueryDisplayName()
{
return GetQSCData(OXSERVICE_QSC_DISPLAYNAME);
}
CString COXService::QueryBinaryPathName()
{
return GetQSCData(OXSERVICE_QSC_BINARYPATHNAME);
}
CString COXService::QueryLoadOrderGroup()
{
return GetQSCData(OXSERVICE_QSC_LOADORDERGROUP);
}
CString COXService::QueryDependencies()
{
return GetQSCData(OXSERVICE_QSC_DEPENDENCIES);
}
CString COXService::QueryStartName()
{
return GetQSCData(OXSERVICE_QSC_SERVICESTARTNAME);
}
DWORD COXService::QueryServiceType()
{
DWORD dwResult;
GetQSCData(OXSERVICE_QSC_SERVICETYPE, &dwResult);
return dwResult;
}
DWORD COXService::QueryStartType()
{
DWORD dwResult;
GetQSCData(OXSERVICE_QSC_STARTTYPE, &dwResult);
return dwResult;
}
DWORD COXService::QueryErrorControl()
{
DWORD dwResult;
GetQSCData(OXSERVICE_QSC_ERRORCONTROL, &dwResult);
return dwResult;
}
DWORD COXService::QueryTagId()
{
DWORD dwResult;
GetQSCData(OXSERVICE_QSC_TAGID, &dwResult);
return dwResult;
}
/////////////////////////////////////////////////////////////////////////////
BOOL COXService::QuerySecurity(SECURITY_INFORMATION dwSecurityInformation,
PSECURITY_DESCRIPTOR lpSecurityDescriptor,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded)
{
return PrepareSCHandle(READ_CONTROL) &&
SetErrCode(::QueryServiceObjectSecurity(m_hSC, dwSecurityInformation,
lpSecurityDescriptor, cbBufSize, pcbBytesNeeded));
}
BOOL COXService::ChangeSecurity(SECURITY_INFORMATION dwSecurityInformation,
PSECURITY_DESCRIPTOR lpSecurityDescriptor)
{
DWORD dwMinimumAccess = 0;
if (dwSecurityInformation & OWNER_SECURITY_INFORMATION ||
dwSecurityInformation & GROUP_SECURITY_INFORMATION)
dwMinimumAccess |= WRITE_OWNER;
if (dwSecurityInformation & DACL_SECURITY_INFORMATION)
dwMinimumAccess |= WRITE_DAC;
return PrepareSCHandle(dwMinimumAccess) &&
SetErrCode(::SetServiceObjectSecurity(m_hSC, dwSecurityInformation,
lpSecurityDescriptor));
}
BOOL COXService::QueryStatus(LPSERVICE_STATUS lpServiceStatus,
BOOL bInterrogateNow /* = FALSE */)
{
if (bInterrogateNow)
return Control(SERVICE_CONTROL_INTERROGATE, lpServiceStatus);
return PrepareSCHandle(SERVICE_QUERY_STATUS) &&
SetErrCode(::QueryServiceStatus(m_hSC, lpServiceStatus));
}
DWORD COXService::QueryCurrentState(BOOL bInterrogateNow /* = FALSE*/)
{
SERVICE_STATUS ss;
VERIFY(QueryStatus(&ss, bInterrogateNow));
return ss.dwCurrentState;
}
CString COXService::QueryDisplayName(LPCTSTR pszKeyName)
{
if (!PrepareSCManager())
return _T("");
CString sResult;
DWORD dwCharNeeded = 256;
BOOL bResult = ::GetServiceDisplayName(c_hSCM, pszKeyName,
sResult.GetBuffer(256), &dwCharNeeded);
sResult.ReleaseBuffer(bResult ? -1 : 0);
return sResult;
}
CString COXService::QueryKeyName(LPCTSTR pszDisplayName)
{
if (!PrepareSCManager())
return _T("");
CString sResult;
DWORD dwCharNeeded = 256;
BOOL bResult = ::GetServiceKeyName(c_hSCM, pszDisplayName,
sResult.GetBuffer(256), &dwCharNeeded);
sResult.ReleaseBuffer(bResult ? -1 : 0);
return sResult;
}
/////////////////////////////////////////////////////////////////////////////
// Static SCManager Functions
SC_HANDLE COXService::GetSCManagerHandle()
{
if (c_hSCM == NULL)
OpenSCManager();
return c_hSCM;
}
BOOL COXService::OpenSCManager(LPCTSTR pszMachineName /* = NULL */,
LPCTSTR pszDatabaseName /* = NULL */,
DWORD dwDesiredAccess /* = SC_MANAGER_ALL_ACCESS */)
{
if (c_hSCM != NULL)
{
if (c_dwSCMAccess == dwDesiredAccess)
{
TRACE0("COXService::OpenSCManager(): desired SCManager was already opened previously.\r\n");
return TRUE;
}
if (!CloseSCManager())
return FALSE;
TRACE0("COXService::OpenSCManager(): previously opened SCManager was closed by this function.\r\n");
}
c_dwSCMAccess = dwDesiredAccess;
return (c_hSCM = ::OpenSCManager(pszMachineName, pszDatabaseName,
dwDesiredAccess)) != NULL;
}
BOOL COXService::LockDatabase()
{
if (c_hSCM != NULL && c_Sclock != NULL)
{
TRACE0("COXService::LockDatabase(): SCM database was already locked.\r\n");
return TRUE;
}
return PrepareSCManager(SC_MANAGER_LOCK) &&
((c_Sclock = ::LockServiceDatabase(c_hSCM)) != NULL);
}
BOOL COXService::UnlockDatabase()
{
// ... SCM has to be opened expicitly or implicitly already
ASSERT(c_hSCM);
if (c_hSCM != NULL)
{
if (c_Sclock == NULL)
{
TRACE0("COXService::UnlockDatabase(): SCM database was not locked.\r\n");
return TRUE;
}
if (::UnlockServiceDatabase(c_Sclock))
{
c_Sclock = NULL;
return TRUE;
}
}
return FALSE;
}
BOOL COXService::QueryDatabaseLockStatus(DWORD& /* bIsLocked */,
CString& sLockOwner,
DWORD& /* dwLockDuration */)
{
if (!PrepareSCManager(SC_MANAGER_QUERY_LOCK_STATUS))
return FALSE;
QUERY_SERVICE_LOCK_STATUS qsls;
DWORD dwBytesNeeded;
qsls.lpLockOwner = sLockOwner.GetBuffer(256);
BOOL bResult = ::QueryServiceLockStatus(c_hSCM, &qsls,
256, &dwBytesNeeded);
if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
sLockOwner.ReleaseBuffer(0);
qsls.lpLockOwner = sLockOwner.GetBuffer(dwBytesNeeded);
bResult = ::QueryServiceLockStatus(c_hSCM, &qsls,
dwBytesNeeded, &dwBytesNeeded);
}
sLockOwner.ReleaseBuffer(bResult ? -1 : 0);
return bResult;
}
BOOL COXService::CloseSCManager()
{
if (c_hSCM == NULL)
return TRUE;
if (c_Sclock != NULL && !UnlockDatabase())
return FALSE;
if (::CloseServiceHandle(c_hSCM))
{
c_hSCM = NULL;
return TRUE;
}
return FALSE;
}
// protected:
BOOL COXService::SetErrCode(BOOL bFunctionSucceeded)
// --- In : bFunctionSucceeded, function return BOOL value
// --- Out :
// --- Returns : same as bFunctionSucceeded (passing it through)
// --- Effect : if last called function is failed, write down last error
{
m_dwErrCode = bFunctionSucceeded ? 0 : ::GetLastError();
#ifdef _DEBUG
if (!bFunctionSucceeded)
{
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, m_dwErrCode, 0, (LPTSTR) &lpMsgBuf, 0, NULL);
TRACE1("COXService Error: %s", lpMsgBuf);
LocalFree(lpMsgBuf);
}
#endif
return bFunctionSucceeded;
}
BOOL COXService::PrepareSCHandle(DWORD dwMinimumAccess /* = SERVICE_ALL_ACCESS */)
// --- In : dwMinimumAccess, the minimum access right of the service handle
// --- Out :
// --- Returns : TRUE if successful; FALSE otherwise
// --- Effect : if service handle is already opened, use it; if not, try to open
// it with full access right (SERVICE_ALL_ACCESS); if failed,
// try to open it with minimum access (dwMinimumAccess).
{
return m_hSC != NULL || Open(SERVICE_ALL_ACCESS) ||
(dwMinimumAccess != SERVICE_ALL_ACCESS && Open(dwMinimumAccess));
}
CString COXService::GetQSCData(int QSC_Code, DWORD* pdwResult /* = NULL */)
// --- In : QSC_Code, the code as above
// --- Out : pdwResult, the DWORD field result
// --- Returns : the string field result
// --- Effect : obtain one field of the query service status
{
CString sResult;
if (pdwResult != NULL)
*pdwResult = 0;
if (!PrepareSCHandle(SERVICE_QUERY_CONFIG))
return _T("");
DWORD dwBytesNeeded;
if (::QueryServiceConfig(m_hSC, NULL, 0, &dwBytesNeeded) ||
::GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
dwBytesNeeded == 0)
{
SetLastError(FALSE);
return _T("");
}
LPQUERY_SERVICE_CONFIG pQSC = (LPQUERY_SERVICE_CONFIG)malloc(dwBytesNeeded);
if (SetErrCode(::QueryServiceConfig(m_hSC, pQSC,
dwBytesNeeded, &dwBytesNeeded)))
{
switch (QSC_Code)
{
case OXSERVICE_QSC_BINARYPATHNAME:
sResult = pQSC->lpBinaryPathName; break;
case OXSERVICE_QSC_LOADORDERGROUP:
sResult = pQSC->lpLoadOrderGroup; break;
case OXSERVICE_QSC_DEPENDENCIES:
NullToBarSeparator(pQSC->lpDependencies);
sResult = pQSC->lpDependencies; break;
case OXSERVICE_QSC_SERVICESTARTNAME:
sResult = pQSC->lpServiceStartName; break;
case OXSERVICE_QSC_DISPLAYNAME:
sResult = pQSC->lpDisplayName; break;
case OXSERVICE_QSC_SERVICETYPE:
*pdwResult = pQSC->dwServiceType; break;
case OXSERVICE_QSC_STARTTYPE:
*pdwResult = pQSC->dwStartType; break;
case OXSERVICE_QSC_ERRORCONTROL:
*pdwResult = pQSC->dwErrorControl; break;
case OXSERVICE_QSC_TAGID:
*pdwResult = pQSC->dwTagId; break;
}
}
free(pQSC);
return sResult;
}
BOOL COXService::PrepareSCManager(DWORD dwMinimumAccess /* = SC_MANAGER_ALL_ACCESS */)
// --- In : dwMinimumAccess, the minimum access right of the SCManager
// --- Out :
// --- Returns : TRUE if successful; FALSE otherwise
// --- Effect : if SCManager is already opened, use it; if not, try to open
// it with full access right (SC_MANAGER_ALL_ACCESS); if failed,
// try to open it with minimum access (dwMinimumAccess).
{
return c_hSCM != NULL || OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS) ||
(dwMinimumAccess != SC_MANAGER_ALL_ACCESS &&
OpenSCManager(NULL, NULL, dwMinimumAccess));
}
void COXService::NullToBarSeparator(LPTSTR pStringData)
// --- In : pStringData : Pointer to string with parts seperated by null chars
// and concluded by two null chars
// --- Out : pStringData : The same string but bars '|' used to seperate the parts
// The string still end in a null char (without a bar)
// --- Returns :
// --- Effect : Converts the string
{
BOOL bPreviousWasNull = FALSE;
BOOL bEnd = FALSE;
BOOL bFirstSymbol=TRUE;
while (!bEnd)
{
// ... String pointer should point to a valid string at all times
ASSERT(AfxIsValidString(pStringData));
if (*pStringData == m_cNull)
{
if(bFirstSymbol)
return;
if (bPreviousWasNull)
{
// ... This char is NULL and so was the previous :
// zero-terminate the string and end the loop
*(pStringData - 1) = m_cNull;
bEnd = TRUE;
}
else
{
// ... This char is NULL but the previous was not:
// replace the zero-char by a bar
*pStringData = m_cBar;
bPreviousWasNull = TRUE;
}
}
else
// ... Encountered a normal (non-NULL-char)
bPreviousWasNull = FALSE;
pStringData++;
bFirstSymbol=FALSE;
}
}
void COXService::BarToNullSeparator(LPTSTR pStringData)
// --- In : pStringData : A string with bars '|' used to seperate the parts
// The string end in a null char (without a bar)
// --- Out : pStringData : The same string but with parts seperated by null chars
// and concluded by two null chars
// --- Returns :
// --- Effect : Converts the string
// Note that the string will grow with one character.
// Enough space should have been allocated before callinbg this function
{
// ... The pStringData should have enough space one additional (null) characters
ASSERT(AfxIsValidAddress(pStringData, (_tcslen(pStringData) + 2) * sizeof(TCHAR)));
// First add an extra NULL character at the end
*(pStringData + _tcslen(pStringData) + 1) = m_cNull;
// Now replace all bars by a NULL character (use _tcstok)
TCHAR * p;
LPCTSTR pNewStringData = UTBStr::tcstok(pStringData, m_pszBar, &p);
while(pNewStringData != NULL)
{
pNewStringData = UTBStr::tcstok(NULL, m_pszBar, &p);
}
}
// end of OXService.cpp