static char *get_instances(const char *object) { PDH_STATUS pdh_status; char *instancelistbuf; DWORD instancelistsize = 0; char *counterlistbuf; DWORD counterlistsize = 0; /* Get necessary size of buffers */ pdh_status = PdhEnumObjectItems(NULL, NULL, object, NULL, &counterlistsize, NULL, &instancelistsize, PERF_DETAIL_WIZARD, 0); /* 2k is dodgy and returns ERROR_SUCCESS even though the buffers were * NULL */ if(pdh_status == PDH_MORE_DATA || pdh_status == ERROR_SUCCESS) { instancelistbuf = sg_malloc(instancelistsize * sizeof(TCHAR)); counterlistbuf = sg_malloc(counterlistsize * sizeof(TCHAR)); if (instancelistbuf != NULL && counterlistbuf != NULL) { pdh_status = PdhEnumObjectItems(NULL, NULL, object, counterlistbuf, &counterlistsize, instancelistbuf, &instancelistsize, PERF_DETAIL_WIZARD, 0); if (pdh_status == ERROR_SUCCESS) { free(counterlistbuf); return instancelistbuf; } } if (counterlistbuf != NULL) free(counterlistbuf); if(instancelistbuf != NULL) free(instancelistbuf); } return NULL; }
int _tmain(int argc, _TCHAR* argv[]) { //3:实现部分 pdhStatus = PdhEnumObjectItems( NULL , NULL , _TEXT ("PhysicalDisk ") , lpsCounterListBuffer , & dwCounterListSize , lpsInstanceListBuffer , & dwInstanceListSize , PERF_DETAIL_WIZARD , 0 ) ; lpsCounterListBuffer = (LPTSTR) malloc(dwCounterListSize * sizeof (TCHAR)) ; //ASSERT ( lpsCounterListBuffer != NULL ) ; lpsInstanceListBuffer= (LPTSTR) malloc(dwInstanceListSize * sizeof (TCHAR)) ; //ASSERT ( lpsInstanceListBuffer != NULL ) ; pdhStatus = PdhEnumObjectItems ( NULL , NULL , _TEXT ("PhysicalDisk ") , lpsCounterListBuffer , & dwCounterListSize , lpsInstanceListBuffer , & dwInstanceListSize , PERF_DETAIL_WIZARD , 0 ) ; //ASSERT ( pdhStatus == ERROR_SUCCESS) ; lpsthisInstance = lpsInstanceListBuffer ; lpsthisCounter = lpsCounterListBuffer; for (; *lpsthisInstance> 0; lpsthisInstance += (lstrlen(lpsthisInstance)+1)) { if (lstrcmp(lpsthisInstance,_TEXT("_Total ")) == 0) continue ; nCount ++ ; } if ( lpsInstanceListBuffer != NULL ) { free ( lpsInstanceListBuffer ) ; lpsInstanceListBuffer = NULL ; } if ( lpsCounterListBuffer != NULL ) { free ( lpsCounterListBuffer ) ; lpsCounterListBuffer = NULL ; } dwCounterListSize = 0 ; dwInstanceListSize = 0 ; return 0; }
JNIEXPORT jobject JNICALL Java_org_krakenapps_winapi_PerformanceCounter_getCounters(JNIEnv *env, jobject obj, jstring category, jstring machine, jint detail) { jclass clzHashMap = (*env)->FindClass(env, "java/util/HashMap"); jmethodID hashMapInit = (*env)->GetMethodID(env, clzHashMap, "<init>", "()V"); jmethodID hashMapPut = (*env)->GetMethodID(env, clzHashMap, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); jobject counter = NULL; LPTSTR categoryName = (LPTSTR)(*env)->GetStringChars(env, category, JNI_FALSE); LPTSTR machineName = machine ? (LPTSTR)(*env)->GetStringChars(env, machine, JNI_FALSE) : NULL; jobjectArray counters = NULL; jobjectArray instances = NULL; LPTSTR lpCounterList = NULL; DWORD dwCounterListLength = 0; LPTSTR lpInstanceList = NULL; DWORD dwInstanceListLength = 0; DWORD stat = 0; if(machineName) { stat = PdhConnectMachine(machineName); if(stat != ERROR_SUCCESS) { fprintf(stderr, "Error in PdhConnectMachine:, 0x%x\n", stat); if(machineName) (*env)->ReleaseStringChars(env, machine, machineName); return NULL; } } PdhEnumObjectItems(NULL, machineName, categoryName, NULL, &dwCounterListLength, NULL, &dwInstanceListLength, detail, 0); lpCounterList = (LPTSTR)malloc(sizeof(TCHAR)*dwCounterListLength); lpInstanceList = (LPTSTR)malloc(sizeof(TCHAR)*dwInstanceListLength); stat = PdhEnumObjectItems(NULL, machineName, categoryName, lpCounterList, &dwCounterListLength, lpInstanceList, &dwInstanceListLength, detail, 0); (*env)->ReleaseStringChars(env, category, categoryName); if(machineName) (*env)->ReleaseStringChars(env, machine, machineName); if(stat != ERROR_SUCCESS) { fprintf(stderr, "Error in PdhEnumObjectItems\n"); return NULL; } counter = counter = (*env)->NewObject(env, clzHashMap, hashMapInit); counters = convertStringArray(env, lpCounterList, dwCounterListLength); instances = convertStringArray(env, lpInstanceList, dwInstanceListLength); free(lpCounterList); free(lpInstanceList); (*env)->CallObjectMethod(env, counter, hashMapPut, (*env)->NewStringUTF(env, "counters"), counters); (*env)->CallObjectMethod(env, counter, hashMapPut, (*env)->NewStringUTF(env, "instances"), instances); return counter; }
BOOL GetIntstancesAndCountersOfObject(CONST std::wstring wsObject, std::vector<std::wstring>& vecInstances, std::vector<std::wstring>& vecCounters) { LPWSTR szDataSource = NULL, szMachineName = NULL, mszCounterList = NULL, mszInstanceList = NULL; DWORD dwCounterListLength = 0, dwInstanceListLength = 0; std::wstringstream wssInstanceName, wssCounterName; LPWSTR szObjectName = new WCHAR[wsObject.length() + 1]; StrCpyW(szObjectName, wsObject.c_str()); PDH_STATUS status = PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, mszCounterList, &dwCounterListLength, mszInstanceList, &dwInstanceListLength, PERF_DETAIL_WIZARD, 0); if (status != PDH_MORE_DATA) { delete[]szObjectName; return FALSE; } mszCounterList = new WCHAR[dwCounterListLength + 1]; mszInstanceList = new WCHAR[dwInstanceListLength + 1]; status = PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, mszCounterList, &dwCounterListLength, mszInstanceList, &dwInstanceListLength, PERF_DETAIL_WIZARD, 0); if (FAILED(status)) { delete[]mszCounterList; delete[]mszInstanceList; delete[]szObjectName; return FALSE; } if (dwInstanceListLength) { for (DWORD c = 0; c < dwInstanceListLength-1; ++c) { if (mszInstanceList[c]) wssInstanceName << mszInstanceList[c]; else { vecInstances.push_back(wssInstanceName.str()); wssInstanceName.str(L""); } } } if (dwCounterListLength) { for (DWORD c = 0; c < dwCounterListLength-1; ++c) { if (mszCounterList[c]) { wssCounterName << mszCounterList[c]; } else { vecCounters.push_back(wssCounterName.str()); wssCounterName.str(L""); } } } delete[]mszCounterList; delete[]mszInstanceList; delete[]szObjectName; return TRUE; }
bool DiskTimeMuninNodePlugin::OpenCounter() { PDH_STATUS status; OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (!GetVersionEx(&osvi) || (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)) return false; //unknown OS or not NT based // Create a PDH query status = PdhOpenQuery(NULL, 0, &m_PerfQuery); if (status != ERROR_SUCCESS) return false; TString logicalDiskCounterName = A2TConvert(g_Config.GetValue("DiskTimePlugin", "CounterNameLogicalDisk", "LogicalDisk")); TString diskTimeCounterName = A2TConvert(g_Config.GetValue("DiskTimePlugin", "CounterNameDiskTime", "% Disk Time")); DWORD counterListLength = 0; DWORD instanceListLength = 0; status = PdhEnumObjectItems(NULL, NULL, logicalDiskCounterName.c_str(), NULL, &counterListLength, NULL, &instanceListLength, PERF_DETAIL_EXPERT, 0); if (status != PDH_MORE_DATA) return false; TCHAR *counterList = new TCHAR[counterListLength]; TCHAR *instanceList = new TCHAR[instanceListLength]; counterList[0] = NULL; instanceList[0] = NULL; status = PdhEnumObjectItems(NULL, NULL, logicalDiskCounterName.c_str(), counterList, &counterListLength, instanceList, &instanceListLength, PERF_DETAIL_EXPERT, 0); if (status != ERROR_SUCCESS) { delete [] counterList; delete [] instanceList; return false; } int pos = 0; TCHAR *instanceName = instanceList; while (instanceName[0] != NULL && instanceName[1] != NULL) { std::string diskName = T2AConvert(instanceName); m_DiskTimeNames.push_back(diskName); while (instanceName[0] != NULL) instanceName++; instanceName++; } delete [] counterList; delete [] instanceList; // We drop the last instance name as it is _Total m_DiskTimeNames.pop_back(); TCHAR diskTimeCounterPath[MAX_PATH] = {0}; HCOUNTER diskTimeCounter; for (size_t i = 0; i < m_DiskTimeNames.size(); i++) { _sntprintf(diskTimeCounterPath, MAX_PATH, _T("\\%s(%s)\\%s"), logicalDiskCounterName.c_str(), m_DiskTimeNames[i].c_str(), diskTimeCounterName.c_str()); // Associate the uptime counter with the query status = PdhAddCounter(m_PerfQuery, diskTimeCounterPath, 0, &diskTimeCounter); if (status != ERROR_SUCCESS) return false; m_DiskTimeCounters.push_back(diskTimeCounter); } // Collect init data status = PdhCollectQueryData(m_PerfQuery); if (status != ERROR_SUCCESS) return false; 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")); 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; }
CPUUsage::CPUUsage( void ) : m_numCounters ( 0 ), m_secondsPerUpdate ( 0.25f ) { // Prepare to monitor CPU performance. std::vector <TCHAR*> vecCounterInstanceNames; PDH_STATUS pdhStatus = ERROR_SUCCESS; LPTSTR szObjectNameBuffer = NULL; DWORD dwObjectNameSize = 0; LPTSTR szCounterListBuffer = NULL; DWORD dwCounterListSize = 0; LPTSTR szInstanceListBuffer = NULL; DWORD dwInstanceListSize = 0; LPTSTR szThisInstance = NULL; // The PDH library does not work as advertised under all conditions; at least some // of the time, it will issue "PDH_INVALID_ARGUMENT" errors on the first call, when // you would normally pass a NULL name pointer and expect a "PDH_MORE_DATA" return // and a valid size. Working around this here by allocating a buffer that's // (hopefully) always "big enough" for the name. szObjectNameBuffer = new TCHAR[m_processorObjectNameMaxSize]; dwObjectNameSize = m_processorObjectNameMaxSize; // Find the "Processor" counter object's friendly local name. Find its size, allocate // a buffer, then get the name. It has a constant index on all machines. pdhStatus = PdhLookupPerfNameByIndex( NULL, // Machine name - local machine since it's NULL m_processorObjectIndex, // Constant index of "Processor" object szObjectNameBuffer, &dwObjectNameSize ); if( pdhStatus == ERROR_SUCCESS ) { // Find the buffer size for the data. pdhStatus = PdhEnumObjectItems( NULL, // Real time source NULL, // Local machine szObjectNameBuffer, // Object to enumerate szCounterListBuffer, // Pass NULL and 0 &dwCounterListSize, // to get length required szInstanceListBuffer, // Buffer size &dwInstanceListSize, // Number of instances PERF_DETAIL_WIZARD, // Counter detail level 0 ); // Under normal conditions, the Enum call will tell us that there's more data, // and it will have set values for the sizes of buffers to return to it. // If that's not true, we'll never collect CPU data on this machine. if( pdhStatus == PDH_MORE_DATA ) { // Allocate the buffers and try the call again. szCounterListBuffer = new TCHAR[dwCounterListSize]; szInstanceListBuffer = new TCHAR[dwInstanceListSize]; if( ( szCounterListBuffer != NULL ) && ( szInstanceListBuffer != NULL ) ) { pdhStatus = PdhEnumObjectItems( NULL, // Real time source NULL, // Local machine szObjectNameBuffer, // Object to enumerate szCounterListBuffer, // Buffer to receive counter list &dwCounterListSize, szInstanceListBuffer, // Buffer to receive instance list &dwInstanceListSize, PERF_DETAIL_WIZARD, // Counter detail level 0 ); // As luck would have it, the counter we want ("% Processor Time" in // English, index #6) is the first one in szCounterListBuffer. Otherwise, // we'd have to iterate down the list to find it. // Now find all instances of that counter: (0), (1), ... (_Total). if( pdhStatus == ERROR_SUCCESS ) { // Walk the instance list. The list can contain one // or more null-terminated strings. The last string // is followed by a second null-terminator. for( szThisInstance = szInstanceListBuffer; *szThisInstance != _T( '\0' ); szThisInstance += _tcslen( szThisInstance ) + 1 ) { // Object name and counter list don't change, but build // a complete counter path from its various parts, which // will look like "\\Processor(_Total)\\% Processor Time" etc. TCHAR szFormat[] = _T( "\\%s(%s)\\%s" ); size_t pathSize = _tcslen( szFormat ) + _tcslen( szObjectNameBuffer ) + _tcslen( szThisInstance ) + _tcslen( szCounterListBuffer ) + 1; // The pathSize is actually a bit bigger than it needs to be, since the // format string characters (e.g. "%s") don't take any space in the // final string. LPTSTR szCounterPath = new TCHAR[ pathSize ]; _stprintf_s( szCounterPath, pathSize, szFormat, szObjectNameBuffer, // "Processor" in English szThisInstance, // "0", "1", etc., as well as "_Total", in all languages szCounterListBuffer ); // "% Processor Time" in English vecCounterInstanceNames.push_back( szCounterPath ); m_numCounters++; } } } } } if( szCounterListBuffer != NULL ) { delete [] szCounterListBuffer; } if( szInstanceListBuffer != NULL ) { delete [] szInstanceListBuffer; } if( szObjectNameBuffer != NULL ) { delete [] szObjectNameBuffer; } // Allocate array for CPU counter results. We always have one more counter than // CPU, since there's a counter for "_Total" CPU usage. If something gets really // wrong here, just claim one CPU. m_CPUCount = m_numCounters - 1; if( m_CPUCount <= 0 ) { m_CPUCount = 1; } m_CPUPercentCounters = new double[m_numCounters]; for( unsigned int i = 0; i < m_numCounters; i++ ) { m_CPUPercentCounters[i] = 0.0f; } // Initialize all processor counters and capture them in the global counter vector. if( m_numCounters > 0 ) { std::vector <TCHAR*>::iterator iter; for( iter = vecCounterInstanceNames.begin(); iter != vecCounterInstanceNames.end(); ++iter ) { ProcessorCounter* procCounter = new ProcessorCounter( *iter ); procCounter->Initialize(); m_vecProcessorCounters.push_back( procCounter ); } // We have the counter name copied in the ProcessorCounter object, so clean up // the name we used here. TCHAR* pTemp = NULL; while( !vecCounterInstanceNames.empty() ) { pTemp = vecCounterInstanceNames.back(); vecCounterInstanceNames.pop_back(); delete [] pTemp; } } // Capture the first value of a tick. QueryPerformanceCounter( &m_LastUpdateTick ); //Calculate the frequency QueryPerformanceFrequency( &m_Frequency ); return; }
JNIEXPORT jobjectArray SIGAR_JNI(win32_Pdh_pdhGetKeys) (JNIEnv *env, jclass cur, jstring cp) { PDH_STATUS status = ERROR_SUCCESS; DWORD counter_list_size = 8096; DWORD instance_list_size = 0; LPTSTR instance_list_buf = (LPTSTR)malloc (counter_list_size * sizeof(TCHAR)); LPTSTR cur_object = NULL; LPCTSTR counter_path = JENV->GetStringChars(env, cp, NULL); jobjectArray array = NULL; status = PdhEnumObjectItems(NULL, NULL, counter_path, instance_list_buf, &counter_list_size, NULL, &instance_list_size, PERF_DETAIL_WIZARD, FALSE); if (status == PDH_MORE_DATA) { /* Allocate the buffers and try the call again. */ if (instance_list_buf != NULL) free(instance_list_buf); instance_list_buf = (LPTSTR)malloc(counter_list_size * sizeof(TCHAR)); instance_list_size = 0; status = PdhEnumObjectItems (NULL, NULL, counter_path, instance_list_buf, &counter_list_size, NULL, &instance_list_size, PERF_DETAIL_WIZARD, 0); } JENV->ReleaseStringChars(env, cp, counter_path); if (status == ERROR_SUCCESS || status == PDH_MORE_DATA) { int i, count; for (cur_object = instance_list_buf, count = 0; *cur_object != 0; cur_object += lstrlen(cur_object) + 1, count++); array = JENV->NewObjectArray(env, count, JENV->FindClass(env, "java/lang/String"), JENV->NewStringUTF(env, "")); if (JENV->ExceptionCheck(env)) { free(instance_list_buf); return NULL; } /* Walk the return instance list, creating an array */ for (cur_object = instance_list_buf, i = 0; *cur_object != 0; i++) { int len = lstrlen(cur_object); jstring s = JENV->NewString(env, (const jchar *)cur_object, len); JENV->SetObjectArrayElement(env, array, i, s); if (JENV->ExceptionCheck(env)) { free(instance_list_buf); return NULL; } cur_object += len + 1; } } else { // An error occured if (instance_list_buf != NULL) free(instance_list_buf); // An error occured win32_throw_exception(env, get_error_message(status)); return NULL; } if (instance_list_buf != NULL) free(instance_list_buf); return array; }
JNIEXPORT jobjectArray JNICALL Java_org_hyperic_hq_plugin_mssql_PDH_pdhGetInstances(JNIEnv *env, jclass, jstring cp) { PDH_STATUS status = ERROR_SUCCESS; DWORD counter_list_size = 0; DWORD instance_list_size = 8096; LPTSTR instance_list_buf = (LPTSTR)malloc ((instance_list_size * sizeof (TCHAR))); LPTSTR cur_object = NULL; LPCTSTR counter_path = (LPCTSTR)env->GetStringChars(cp, 0); jobjectArray array = NULL; status = PdhEnumObjectItems(NULL, NULL, counter_path, NULL, &counter_list_size, instance_list_buf, &instance_list_size, PERF_DETAIL_WIZARD, FALSE); if (status == PDH_MORE_DATA && instance_list_size > 0) { // Allocate the buffers and try the call again. if (instance_list_buf != NULL) free(instance_list_buf); instance_list_buf = (LPTSTR)malloc((instance_list_size * sizeof (TCHAR))); counter_list_size = 0; status = PdhEnumObjectItems (NULL, NULL, counter_path, NULL, &counter_list_size, instance_list_buf, &instance_list_size, PERF_DETAIL_WIZARD, FALSE); } env->ReleaseStringChars(cp, (const jchar *)counter_path); // Still may get PDH_ERROR_MORE data after the first reallocation, // but that is OK for just browsing the instances if (status == ERROR_SUCCESS || status == PDH_MORE_DATA) { int i, count; for (cur_object = instance_list_buf, count = 0; *cur_object != 0; cur_object += lstrlen(cur_object) + 1, count++); array = env->NewObjectArray(count, env->FindClass("java/lang/String"), env->NewStringUTF("")); if (env->ExceptionCheck()) { free(instance_list_buf); return NULL; } /* Walk the return instance list, creating an array */ for (cur_object = instance_list_buf, i = 0; *cur_object != 0; i++) { int len = lstrlen(cur_object); jstring s = env->NewString((const jchar *)cur_object, len); env->SetObjectArrayElement(array, i, s); if (env->ExceptionCheck()) { free(instance_list_buf); return NULL; } cur_object += len + 1; } } else { if (instance_list_buf != NULL) free(instance_list_buf); // An error occured plugin_throw_exception(env, get_error_message(status)); return NULL; } if (instance_list_buf != NULL) free(instance_list_buf); return array; }