Skip to content

Commit

Permalink
Fix PdhTest + update PdhEnumObjectItems
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiasblaesing committed Jul 30, 2018
1 parent e0a28a3 commit 14b746f
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 96 deletions.
8 changes: 6 additions & 2 deletions contrib/platform/src/com/sun/jna/platform/win32/Pdh.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
*/
package com.sun.jna.platform.win32;

import java.util.List;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
Expand Down Expand Up @@ -55,6 +53,12 @@ public interface Pdh extends StdCallLibrary {
/** Maximum full counter log name length. */
int PDH_MAX_DATASOURCE_PATH = 1024;

int PDH_MORE_DATA = 0x800007D2;
int PDH_INVALID_ARGUMENT = 0xC0000BBD;
int PDH_MEMORY_ALLOCATION_FAILURE = 0xC0000BBB;
int PDH_CSTATUS_NO_MACHINE = 0x800007D0;
int PDH_CSTATUS_NO_OBJECT = 0xC0000BB8;

/* TODO
* LPVOID CALLBACK AllocateMemory(_In_ SIZE_T AllocSize,_In_ LPVOID pContext)
* void CALLBACK FreeMemory(LPVOID pBuffer,LPVOID pContext)
Expand Down
170 changes: 84 additions & 86 deletions contrib/platform/src/com/sun/jna/platform/win32/PdhUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.DWORDByReference;
import java.util.Collections;

/**
* Pdh utility API.
Expand Down Expand Up @@ -113,9 +114,8 @@ public static int PdhLookupPerfIndexByEnglishName(String szNameBuffer) {

/**
* Utility method to call Pdh's PdhEnumObjectItems that allocates the
* required memory for the mszCounterList parameter based on the type
* mapping used, calls to PdhEnumObjectItems, and returns the received lists
* of strings.
* required memory for the lists parameters based on the type mapping used,
* calls to PdhEnumObjectItems, and returns the received lists of strings.
*
* @param szDataSource
* String that specifies the name of the log file used to
Expand All @@ -137,113 +137,111 @@ public static int PdhLookupPerfIndexByEnglishName(String szNameBuffer) {
* returned.
* @return Returns a List of Strings of the counters for the object.
*/
public static List<String> PdhEnumObjectItemCounters(String szDataSource, String szMachineName, String szObjectName,
public static PdhEnumObjectItems PdhEnumObjectItems(String szDataSource, String szMachineName, String szObjectName,
int dwDetailLevel) {
List<String> counters = new ArrayList<String>();
List<String> instances = new ArrayList<String>();

// Call once to get string lengths
DWORDByReference pcchCounterListLength = new DWORDByReference(new DWORD(0));
DWORDByReference pcchInstanceListLength = new DWORDByReference(new DWORD(0));
Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, null, pcchCounterListLength, null,
int result = Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, null, pcchCounterListLength, null,
pcchInstanceListLength, dwDetailLevel, 0);
if(result != WinError.ERROR_SUCCESS && result != Pdh.PDH_MORE_DATA) {
throw new Win32Exception(result);
}

// Can't allocate 0 memory if no counters
if (pcchCounterListLength.getValue().intValue() < 1) {
return counters;
Memory mszCounterList = null;
Memory mszInstanceList = null;

if (pcchCounterListLength.getValue().intValue() > 0) {
mszCounterList = new Memory(pcchCounterListLength.getValue().intValue() * CHAR_TO_BYTES);
}

if (pcchInstanceListLength.getValue().intValue() > 0) {
mszInstanceList = new Memory(pcchInstanceListLength.getValue().intValue() * CHAR_TO_BYTES);
}

result = Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, mszCounterList,
pcchCounterListLength, mszInstanceList, pcchInstanceListLength, dwDetailLevel, 0);

if(result != WinError.ERROR_SUCCESS) {
throw new Win32Exception(result);
}
// Allocate memory and call again to populate strings
Memory mszCounterList = new Memory(pcchCounterListLength.getValue().intValue() * CHAR_TO_BYTES);
// Don't need the instances
pcchInstanceListLength.getValue().setValue(0);
Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, mszCounterList,
pcchCounterListLength, null, pcchInstanceListLength, dwDetailLevel, 0);

// Fetch counters
int offset = 0;
while (offset < mszCounterList.size()) {
String s = null;
if (CHAR_TO_BYTES == 1) {
s = mszCounterList.getString(offset);
} else {
s = mszCounterList.getWideString(offset);
if (mszCounterList != null) {
int offset = 0;
while (offset < mszCounterList.size()) {
String s = null;
if (CHAR_TO_BYTES == 1) {
s = mszCounterList.getString(offset);
} else {
s = mszCounterList.getWideString(offset);
}
// list ends with double null
if (s.isEmpty()) {
break;
}
counters.add(s);
// Increment for string + null terminator
offset += (s.length() + 1) * CHAR_TO_BYTES;
}
// list ends with double null
if (s.isEmpty()) {
break;
}

if(mszInstanceList != null) {
int offset = 0;
while (offset < mszInstanceList.size()) {
String s = null;
if (CHAR_TO_BYTES == 1) {
s = mszInstanceList.getString(offset);
} else {
s = mszInstanceList.getWideString(offset);
}
// list ends with double null
if (s.isEmpty()) {
break;
}
instances.add(s);
// Increment for string + null terminator
offset += (s.length() + 1) * CHAR_TO_BYTES;
}
counters.add(s);
// Increment for string + null terminator
offset += (s.length() + 1) * CHAR_TO_BYTES;
}

return counters;
return new PdhEnumObjectItems(counters, instances);
}

/**
* Utility method to call Pdh's PdhEnumObjectItems that allocates the
* required memory for the mszInstanceList parameters based on the type
* mapping used, calls to PdhEnumObjectItems, and returns the received lists
* of strings.
*
* @param szDataSource
* String that specifies the name of the log file used to
* enumerate the counter and instance names. If NULL, the
* function uses the computer specified in the szMachineName
* parameter to enumerate the names.
* @param szMachineName
* String that specifies the name of the computer that contains
* the counter and instance names that you want to enumerate.
* Include the leading slashes in the computer name, for example,
* \\computername. If the szDataSource parameter is NULL, you can
* set szMachineName to NULL to specify the local computer.
* @param szObjectName
* String that specifies the name of the object whose counter and
* instance names you want to enumerate.
* @param dwDetailLevel
* Detail level of the performance items to return. All items
* that are of the specified detail level or less will be
* returned.
* @return Returns a Lists of Strings of the instances of the object.
*/
public static List<String> PdhEnumObjectItemInstances(String szDataSource, String szMachineName,
String szObjectName, int dwDetailLevel) {
List<String> instances = new ArrayList<String>();

// Call once to get string lengths
DWORDByReference pcchCounterListLength = new DWORDByReference(new DWORD(0));
DWORDByReference pcchInstanceListLength = new DWORDByReference(new DWORD(0));
Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, null, pcchCounterListLength, null,
pcchInstanceListLength, dwDetailLevel, 0);
public static class PdhEnumObjectItems {
private final List<String> counters;
private final List<String> instances;

// Can't allocate 0 memory if no instances
if (pcchInstanceListLength.getValue().intValue() < 1) {
public PdhEnumObjectItems(List<String> counters, List<String> instances) {
this.counters = Collections.unmodifiableList(emptyListForNullList(counters));
this.instances = Collections.unmodifiableList(emptyListForNullList(instances));
}

public List<String> getCounters() {
return counters;
}

public List<String> getInstances() {
return instances;
}
// Allocate memory and call again to populate strings
Memory mszInstanceList = new Memory(pcchInstanceListLength.getValue().intValue() * CHAR_TO_BYTES);
// Don't need the counters
pcchCounterListLength.getValue().setValue(0);
Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, null, pcchCounterListLength,
mszInstanceList, pcchInstanceListLength, dwDetailLevel, 0);

// Fetch instances
int offset = 0;
while (offset < mszInstanceList.size()) {
String s = null;
if (CHAR_TO_BYTES == 1) {
s = mszInstanceList.getString(offset);

private List<String> emptyListForNullList (List<String> inputList) {
if(inputList == null) {
return Collections.<String>emptyList();
} else {
s = mszInstanceList.getWideString(offset);
}
// list ends with double null
if (s.isEmpty()) {
break;
return inputList;
}
instances.add(s);
// Increment for string + null terminator
offset += (s.length() + 1) * CHAR_TO_BYTES;
}

return instances;
@Override
public String toString() {
return "PdhEnumObjectItems{" + "counters=" + counters + ", instances=" + instances + '}';
}


}
}
14 changes: 6 additions & 8 deletions contrib/platform/test/com/sun/jna/platform/win32/PdhTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.junit.Test;

import com.sun.jna.Native;
import com.sun.jna.platform.win32.Pdh.PDH_COUNTER_PATH_ELEMENTS;
import com.sun.jna.platform.win32.Pdh.PDH_RAW_COUNTER;
import com.sun.jna.platform.win32.PdhUtil.PdhEnumObjectItems;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.DWORDByReference;
import com.sun.jna.platform.win32.WinNT.HANDLE;
Expand Down Expand Up @@ -182,19 +182,17 @@ public void testLookupPerfIndex() {
@Test
public void testEnumObjectItems() {
if (AbstractWin32TestSupport.isEnglishLocale) {
String processorStr = "Processor";
String processorStr = "Processor";
String processorTimeStr = "% Processor Time";

// Fetch the counter and instance names
List<String> instances = PdhUtil.PdhEnumObjectItemInstances(null, null, processorStr, 100);
PdhEnumObjectItems objects = PdhUtil.PdhEnumObjectItems(null, null, processorStr, 100);

// Should have at least one processor and total instance
assertTrue(instances.contains("0"));
assertTrue(instances.contains("_Total"));
assertTrue(objects.getInstances().contains("0"));
assertTrue(objects.getInstances().contains("_Total"));

// Should have a "% Processor Time" counter
List<String> counters = PdhUtil.PdhEnumObjectItemCounters(null, null, processorStr, 100);
assertTrue(counters.contains(processorTimeStr));
assertTrue(objects.getCounters().contains(processorTimeStr));
} else {
System.err.println("testEnumObjectItems test can only be run with english locale.");
}
Expand Down

0 comments on commit 14b746f

Please sign in to comment.