bool PerfCounterMuninNodePlugin::OpenCounter()
{
  PDH_STATUS status;  

  m_Name = m_SectionName.substr(strlen(PerfCounterMuninNodePlugin::SectionPrefix));

  OSVERSIONINFO osvi;    
  ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  if (!GetVersionEx(&osvi) || (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)) {
	  _Module.LogError("PerfCounter plugin: %s: unknown OS or not NT based", m_Name.c_str());
	  return false; //unknown OS or not NT based
  }

  // Create a PDH query
  status = PdhOpenQuery(NULL, 0, &m_PerfQuery);
  if (status != ERROR_SUCCESS) {
	  _Module.LogError("PerfCounter plugin: %s: PdhOpenQuery error=%x", m_Name.c_str(), status);
	  return false;
  }

  TString objectName = A2TConvert(g_Config.GetValue(m_SectionName, "Object", "LogicalDisk"));
  TString counterName = A2TConvert(g_Config.GetValue(m_SectionName, "Counter", "% Disk Time"));
  
  DWORD counterListLength = 0;  
  DWORD instanceListLength = 0;
  if (g_Config.GetValueB(m_SectionName, "UseEnglishObjectNames", true)) {
	  counterName = GetPdhCounterLocalizedName(counterName.c_str());
	  objectName = GetPdhCounterLocalizedName(objectName.c_str());
  }
  status = PdhEnumObjectItems(NULL, NULL, objectName.c_str(), NULL, &counterListLength, NULL, &instanceListLength, PERF_DETAIL_EXPERT, 0);
  if (status != PDH_MORE_DATA) {
	  _Module.LogError("PerfCounter plugin: %s: PdhEnumObjectItems error=%x", m_Name.c_str(), status);
	  return false;
  }

  TCHAR *counterList = new TCHAR[counterListLength+2];
  TCHAR *instanceList = new TCHAR[instanceListLength+2];
  counterList[0] = NULL;
  instanceList[0] = NULL;
  counterList[1] = NULL;
  instanceList[1] = NULL;

  status = PdhEnumObjectItems(NULL, NULL, objectName.c_str(), counterList, &counterListLength, instanceList, &instanceListLength, PERF_DETAIL_EXPERT, 0);
  if (status != ERROR_SUCCESS) {
    delete [] counterList;
    delete [] instanceList;
	_Module.LogError("PerfCounter plugin: %s: PdhEnumObjectItems error=%x", m_Name.c_str(), status);
    return false;  
  }

  int pos = 0;
  TCHAR *instanceName = instanceList;
  while (instanceName[0] != NULL) {
    std::string counterInstanceName = T2AConvert(instanceName);
    m_CounterNames.push_back(counterInstanceName);
    while (instanceName[0] != NULL)
      instanceName++;
    instanceName++;
  }
  delete [] counterList;
  delete [] instanceList;

  TCHAR counterPath[MAX_PATH] = {0};
  HCOUNTER counterHandle;
  if (!m_CounterNames.empty()) {
    if (g_Config.GetValueB(m_SectionName, "DropTotal", true)) {
      assert(m_CounterNames.back().compare("_Total") == 0);
      // We drop the last instance name as it is _Total
      m_CounterNames.pop_back();
    }

    for (size_t i = 0; i < m_CounterNames.size(); i++) {
      TString instanceNameStr = A2TConvert(m_CounterNames[i]);
      _sntprintf(counterPath, MAX_PATH, _T("\\%s(%s)\\%s"), objectName.c_str(), instanceNameStr.c_str(), counterName.c_str());
      // Associate the uptime counter with the query
      status = PdhAddCounter(m_PerfQuery, counterPath, 0, &counterHandle);
	  if (status != ERROR_SUCCESS) {
		  _Module.LogError("PerfCounter plugin: %s: PDH add counter error=%x", m_Name.c_str(), status);
		  return false;
	  }
      
      m_Counters.push_back(counterHandle);
    }
  } else {
    // A counter with a single instance (Uptime for example)
    m_CounterNames.push_back("0");
    _sntprintf(counterPath, MAX_PATH, _T("\\%s\\%s"), objectName.c_str(), counterName.c_str());
    // Associate the uptime counter with the query
    status = PdhAddCounter(m_PerfQuery, counterPath, 0, &counterHandle);
	if (status != ERROR_SUCCESS) {
		_Module.LogError("PerfCounter plugin: %s: PDH add counter error=%x", m_Name.c_str(), status);
		return false;
	}
    
    m_Counters.push_back(counterHandle);
  }
  
  // Collect init data
  status = PdhCollectQueryData(m_PerfQuery);
  if (status != ERROR_SUCCESS) {
	  if (status == PDH_INVALID_HANDLE) {
		  _Module.LogError("PerfCounter plugin: %s: PDH collect data: PDH_INVALID_HANDLE", m_Name.c_str());
		  return false;
	  }
	  if (status == PDH_NO_DATA) {
		  _Module.LogError("PerfCounter plugin: %s: PDH collect data: PDH_NO_DATA", m_Name.c_str());
		  return false;
	  }
	  _Module.LogError("PerfCounter plugin: %s: PDH collect data error", m_Name.c_str());
	  return false;
  }

  // Setup Counter Format
  m_dwCounterFormat = PDH_FMT_DOUBLE;
  std::string counterFormatStr = g_Config.GetValue(m_SectionName, "CounterFormat", "double");
  if (!counterFormatStr.compare("double")
    || !counterFormatStr.compare("float")) {
    m_dwCounterFormat = PDH_FMT_DOUBLE;

  } else if (!counterFormatStr.compare("int") 
    || !counterFormatStr.compare("long")) {
    m_dwCounterFormat = PDH_FMT_LONG;

  } else if (!counterFormatStr.compare("int64") 
    || !counterFormatStr.compare("longlong") 
    || !counterFormatStr.compare("large")) {
    m_dwCounterFormat = PDH_FMT_LARGE;

  } else {
	  _Module.LogError("PerfCounter plugin: %s: Unknown CounterFormat", m_Name.c_str());
	  assert(!"Unknown CounterFormat!");
  }

  m_CounterMultiply = g_Config.GetValueF(m_SectionName, "CounterMultiply", 1.0);

  return true;
}
bool PerfCounterMuninNodePlugin::OpenCounter()
{
  PDH_STATUS status;  

  m_Name = m_SectionName.substr(strlen(PerfCounterMuninNodePlugin::SectionPrefix));

  OSVERSIONINFO osvi;    
  ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  if (!GetVersionEx(&osvi) || (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)) {
	  _Module.LogError("PerfCounter plugin: %s: unknown OS or not NT based", m_Name.c_str());
	  return false; //unknown OS or not NT based
  }

  // Create a PDH query
  status = PdhOpenQuery(NULL, 0, &m_PerfQuery);
  if (status != ERROR_SUCCESS) {
	  _Module.LogError("PerfCounter plugin: %s: PdhOpenQuery error=%x", m_Name.c_str(), status);
	  return false;
  }

  TString objectName = A2TConvert(g_Config.GetValue(m_SectionName, "Object", "LogicalDisk"));
  TString counterName = A2TConvert(g_Config.GetValue(m_SectionName, "Counter", "% Disk Time"));
  TString instanceName = A2TConvert(g_Config.GetValue(m_SectionName, "Instance", "*"));

  bool useEnglishNames = g_Config.GetValueB(m_SectionName, "UseEnglishObjectNames", true);
  if (useEnglishNames) {
	  counterName = GetPdhCounterLocalizedName(counterName.c_str());
	  objectName = GetPdhCounterLocalizedName(objectName.c_str());
	  // NB: instance names are not localized
  }

  TCHAR *counterPath = new TCHAR[MAX_PATH];

  status = _sntprintf(counterPath, MAX_PATH, _T("\\%s(%s)\\%s"), objectName.c_str(), instanceName.c_str(), counterName.c_str());
  DWORD pathListBufsz = 0;
  status = PdhExpandWildCardPath(NULL, counterPath, NULL, &pathListBufsz, 0);
  if (status != PDH_MORE_DATA && status != PDH_INSUFFICIENT_BUFFER) {
	  _Module.LogError("PerfCounter plugin: %s: PdhExpandWildCardPath error=%x", m_Name.c_str(), status);
	  return false;
  }
  TCHAR *pathList = new TCHAR[pathListBufsz+2];
  status = PdhExpandWildCardPath(NULL, counterPath, (PZZTSTR)pathList, &pathListBufsz, 0);
  if (status != ERROR_SUCCESS) {
	  _Module.LogError("PerfCounter plugin: %s: PdhExpandWildCardPath error=%x", m_Name.c_str(), status);
	  return false;
  }

  // read config
  TString includeRE = A2TConvert(g_Config.GetValue(m_SectionName, "IncludePaths", ".+"));
  TString excludeRE = A2TConvert(g_Config.GetValue(m_SectionName, "ExcludePaths", "^$"));

  // create regex matchers
  CRegexpT <TCHAR> includeRegEx(includeRE.c_str(), IGNORECASE);
  CRegexpT <TCHAR> excludeRegEx(excludeRE.c_str(), IGNORECASE);

  HCOUNTER counterHandle;
  for (; *pathList; pathList += _tcslen(pathList) + 1) {
	  /* anatomy of a PDH path: \\machine\object(instance)\counter
	   * anomalies of a PDH path: the instance name is optional, and
	   * may contain parantheses and/or backslashes
	   * thus, the safest way is to check for the first '(' and the
	   * last '\' to separate the object, counter, instance names
	   */
	  int backslashes[2] = {0, 0};
	  int para = 0;
	  int idx;
	  for (idx = 2; pathList[idx]; idx++) {
		  if (pathList[idx] == '\\') {
			  if (backslashes[0]) {
				  backslashes[1] = idx;
			  } else {
				  backslashes[0] = idx;
			  }
		  } else if (pathList[idx] == '(' && (!para) && backslashes[0] && (!backslashes[1])) {
			  para = idx;
		  }
	  }
	  TCHAR *matchPath;
	  // use regex matching either on the original path or the
	  // back-translated constructed path
	  if (useEnglishNames) {
		  DWORD instPos = para ? para : backslashes[1];
		  TCHAR *oName = new TCHAR[instPos - backslashes[0]];
		  TCHAR *cName = new TCHAR[idx - backslashes[1] + 1];
		  TCHAR *iName = new TCHAR[backslashes[1] - para + 1];
		  // copy the object name
		  wcsncpy(oName, pathList + backslashes[0] + 1, instPos - backslashes[0] - 1);
		  oName[instPos - backslashes[0] - 1] = 0;
		  // copy the counter name (end of complete path, so \0 already exists)
		  wcsncpy(cName, pathList + backslashes[1] + 1, idx - backslashes[1]);
		  cName[idx - backslashes[1]] = 0;
		  // if there's an instance name, copy it, too.
		  if (para) {
			  wcsncpy(iName, pathList + para, backslashes[1] - para);
		  }
		  iName[backslashes[1] - para] = 0;
		  matchPath = new TCHAR[MAX_PATH];
		  _snwprintf(matchPath, MAX_PATH, _T("\\%s%s\\%s"), GetPdhCounterEnglishName(oName), iName, GetPdhCounterEnglishName(cName));
		  delete oName;
		  delete cName;
		  delete iName;
	  } else {
		  matchPath = pathList;
	  }
	  // handle includes & excludes
	  if (!includeRegEx.MatchExact(matchPath).IsMatched()
		  || excludeRegEx.MatchExact(matchPath).IsMatched()) {
		  if (useEnglishNames) {
			  delete matchPath;
		  }
		  continue;
	  }
	  if (useEnglishNames) {
		  delete matchPath;
	  }
	  // add the counter
	  status = PdhAddCounter(m_PerfQuery, pathList, 0, &counterHandle);
	  if (status != ERROR_SUCCESS) {
		  _Module.LogError("PerfCounter plugin: %s: PDH add counter error=%x", m_Name.c_str(), status);
		  return false;
	  }

	  // replace the backslash before the counter name with a space
	  pathList[backslashes[1]] = ' ';

	  std::string cn = W2IConvert(pathList + (para ? para : (backslashes[1] + 1)));
	  _Module.LogEvent("PerfCounter plugin: %s: added counter %s", m_Name.c_str(), cn.c_str());
	  m_Counters.push_back(counterHandle);
	  m_CounterNames.push_back(cn);
  }
  
  // Collect init data
  status = PdhCollectQueryData(m_PerfQuery);
  if (status != ERROR_SUCCESS) {
	  if (status == PDH_INVALID_HANDLE) {
		  _Module.LogError("PerfCounter plugin: %s: PDH collect data: PDH_INVALID_HANDLE", m_Name.c_str());
		  return false;
	  }
	  if (status == PDH_NO_DATA) {
		  _Module.LogError("PerfCounter plugin: %s: PDH collect data: PDH_NO_DATA", m_Name.c_str());
		  return false;
	  }
	  _Module.LogError("PerfCounter plugin: %s: PDH collect data error", m_Name.c_str());
	  return false;
  }

  // Setup Counter Format
  m_dwCounterFormat = PDH_FMT_DOUBLE;
  std::string counterFormatStr = g_Config.GetValue(m_SectionName, "CounterFormat", "double");
  if (!counterFormatStr.compare("double")
    || !counterFormatStr.compare("float")) {
    m_dwCounterFormat = PDH_FMT_DOUBLE;

  } else if (!counterFormatStr.compare("int") 
    || !counterFormatStr.compare("long")) {
    m_dwCounterFormat = PDH_FMT_LONG;

  } else if (!counterFormatStr.compare("int64") 
    || !counterFormatStr.compare("longlong") 
    || !counterFormatStr.compare("large")) {
    m_dwCounterFormat = PDH_FMT_LARGE;

  } else {
	  _Module.LogError("PerfCounter plugin: %s: Unknown CounterFormat", m_Name.c_str());
	  assert(!"Unknown CounterFormat!");
  }

  m_CounterMultiply = g_Config.GetValueF(m_SectionName, "CounterMultiply", 1.0);

  return true;
}