BOOL CNTScmService::QueryTrigger(PSERVICE_TRIGGER_INFO& pTriggerInfo) const
{
  //Validate our parameters
  ATLASSERT(m_hService != NULL);
  ATLASSERT(pTriggerInfo == NULL); //To prevent double overwrites, this function
                                   //asserts if you do not send in a NULL pointer

  //Check to see if the function pointer is available
  if (m_lpfnQueryServiceConfig2 == NULL)
  {
    ATLTRACE(_T("CNTScmService::QueryTrigger, QueryServiceConfig2 function is not supported on this OS. You need to be running at least Windows 7 / Windows 2008 R2 to use this function\n"));
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return FALSE;
  }

  //Call through the function pointer
  DWORD dwBytesNeeded = 0;
  BOOL bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_TRIGGER_INFO, NULL, 0, &dwBytesNeeded);
  if (!bSuccess && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  {
    pTriggerInfo = reinterpret_cast<PSERVICE_TRIGGER_INFO>(new BYTE[dwBytesNeeded]);
    bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_TRIGGER_INFO, reinterpret_cast<LPBYTE>(pTriggerInfo), dwBytesNeeded, &dwBytesNeeded);
  }

  return bSuccess;
}
BOOL CNTScmService::QueryDescription(CString& sDescription) const
{
  //Validate our parameters
  ASSERT(m_hService != NULL);

  //Check to see if the function pointer is available
  if (m_lpfnQueryServiceConfig2 == NULL)
  {
    TRACE(_T("CNTScmService::QueryDescription, QueryServiceConfig2 function is not supported on this OS. You need to be running at least Windows 2000 to use this function\n"));
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return FALSE;
  }

  //Call through the function pointer
  DWORD dwBytesNeeded = 0;
  BOOL bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_DESCRIPTION, NULL, 0, &dwBytesNeeded);
  if (!bSuccess && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  {
    //Allocate some memory for the API
    ATL::CHeapPtr<BYTE> lpData;
    if (!lpData.Allocate(dwBytesNeeded))
    {
      SetLastError(ERROR_OUTOFMEMORY);
      return FALSE;
    }

    bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_DESCRIPTION, lpData, dwBytesNeeded, &dwBytesNeeded);
    if (bSuccess)
      sDescription = (reinterpret_cast<LPSERVICE_DESCRIPTION>(lpData.m_pData))->lpDescription;
  }

  return bSuccess;
}
BOOL CNTScmService::QueryRequiredPrivileges(CNTServiceStringArray& privileges) const
{
  //Validate our parameters
  ATLASSERT(m_hService != NULL);

  //Empty our the array
#ifdef CNTSERVICE_MFC_EXTENSIONS
  privileges.RemoveAll();
#else
  privileges.clear();
#endif

  //Check to see if the function pointer is available
  if (m_lpfnQueryServiceConfig2 == NULL)
  {
    ATLTRACE(_T("CNTScmService::QueryRequiredPrivileges, QueryServiceConfig2 function is not supported on this OS. You need to be running at least Windows Vista / Windows 2008 to use this function\n"));
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return FALSE;
  }

  //Call through the function pointer
  DWORD dwBytesNeeded = 0;
  BOOL bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO, NULL, 0, &dwBytesNeeded);
  if (!bSuccess && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  {
    //Allocate some memory for the API
    ATL::CHeapPtr<BYTE> lpBuffer;
    if (!lpBuffer.Allocate(dwBytesNeeded))
    {
      SetLastError(ERROR_OUTOFMEMORY);
      return FALSE;
    }

    bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO, lpBuffer, dwBytesNeeded, &dwBytesNeeded);
    if (bSuccess)
    {
      LPTSTR lpszStrings = reinterpret_cast<LPTSTR>(lpBuffer.m_pData);
      while (lpszStrings[0] != 0)
      {
      #ifdef CNTSERVICE_MFC_EXTENSIONS
        privileges.Add(lpszStrings);
      #else
        privileges.push_back(lpszStrings);
      #endif
        lpszStrings += (_tcslen(lpszStrings ) + 1);
      }
    }
  }

  return bSuccess;
}
BOOL CNTScmService::QueryPreferredNode(USHORT& usPreferredNode, BOOL& bDelete) const
{
  //Validate our parameters
  ATLASSERT(m_hService != NULL);

  //Check to see if the function pointer is available
  if (m_lpfnQueryServiceConfig2 == NULL)
  {
    ATLTRACE(_T("CNTScmService::QueryPreferredNode, QueryServiceConfig2 function is not supported on this OS. You need to be running at least Windows 7 / Windows 2008 R2 to use this function\n"));
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return FALSE;
  }

  //Call through the function pointer
  SERVICE_PREFERRED_NODE_INFO spni;
  DWORD dwBytesNeeded = 0;
  BOOL bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_PREFERRED_NODE, reinterpret_cast<LPBYTE>(&spni), sizeof(spni), &dwBytesNeeded);
  if (bSuccess)
  {
    usPreferredNode = spni.usPreferredNode;
    bDelete = spni.fDelete;
  }

  return bSuccess;
}
BOOL CNTScmService::QueryLaunchProtected(DWORD& dwLaunchProtected) const
{
  //Validate our parameters
  ATLASSERT(m_hService != NULL);

  //Check to see if the function pointer is available
  if (m_lpfnQueryServiceConfig2 == NULL)
  {
    ATLTRACE(_T("CNTScmService::QueryLaunchProtected, QueryServiceConfig2 function is not supported on this OS. You need to be running at least Windows 8.1 / Windows 2012 R2 to use this function\n"));
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return FALSE;
  }

  //Call through the function pointer
  _SERVICE_LAUNCH_PROTECTED_INFO slpi;
  DWORD dwBytesNeeded = 0;
  BOOL bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_LAUNCH_PROTECTED, reinterpret_cast<LPBYTE>(&slpi), sizeof(slpi), &dwBytesNeeded);
  if (bSuccess)
    dwLaunchProtected = slpi.dwLaunchProtected;

  return bSuccess;
}
BOOL CNTScmService::QueryPreShutdown(DWORD& dwPreshutdownTimeout) const
{
  //Validate our parameters
  ATLASSERT(m_hService != NULL);

  //Check to see if the function pointer is available
  if (m_lpfnQueryServiceConfig2 == NULL)
  {
    ATLTRACE(_T("CNTScmService::QueryPreShutdown, QueryServiceConfig2 function is not supported on this OS. You need to be running at least Windows Vista / Windows 2008 to use this function\n"));
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return FALSE;
  }

  //Call through the function pointer
  SERVICE_PRESHUTDOWN_INFO spsi;
  DWORD dwBytesNeeded = 0;
  BOOL bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_PRESHUTDOWN_INFO, reinterpret_cast<LPBYTE>(&spsi), sizeof(spsi), &dwBytesNeeded);
  if (bSuccess)
    dwPreshutdownTimeout = spsi.dwPreshutdownTimeout;

  return bSuccess;
}
BOOL CNTScmService::QueryFailureActionsFlag(BOOL& bFailureActionsOnNonCrashFailures) const
{
  //Validate our parameters
  ATLASSERT(m_hService != NULL);

  //Check to see if the function pointer is available
  if (m_lpfnQueryServiceConfig2 == NULL)
  {
    ATLTRACE(_T("CNTScmService::QueryFailureActionsFlag, QueryServiceConfig2 function is not supported on this OS. You need to be running at least Windows Vista / Windows 2008 to use this function\n"));
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return FALSE;
  }

  //Call through the function pointer
  SERVICE_FAILURE_ACTIONS_FLAG sfaf;
  DWORD dwBytesNeeded = 0;
  BOOL bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, reinterpret_cast<LPBYTE>(&sfaf), sizeof(sfaf), &dwBytesNeeded);
  if (bSuccess)
    bFailureActionsOnNonCrashFailures = sfaf.fFailureActionsOnNonCrashFailures;

  return bSuccess;
}
BOOL CNTScmService::QueryDelayAutoStart(BOOL& bDelayedAutoStart) const
{
  //Validate our parameters
  ATLASSERT(m_hService != NULL);

  //Check to see if the function pointer is available
  if (m_lpfnQueryServiceConfig2 == NULL)
  {
    ATLTRACE(_T("CNTScmService::QueryDelayAutoStart, QueryServiceConfig2 function is not supported on this OS. You need to be running at least Windows Vista / Windows 2008 to use this function\n"));
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return FALSE;
  }

  //Call through the function pointer
  SERVICE_DELAYED_AUTO_START_INFO sdasi;
  DWORD dwBytesNeeded = 0;
  BOOL bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, reinterpret_cast<LPBYTE>(&sdasi), sizeof(sdasi), &dwBytesNeeded);
  if (bSuccess)
    bDelayedAutoStart = sdasi.fDelayedAutostart;

  return bSuccess;
}