From 14b746f77d6962733475b0b575baa7be95907954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Bl=C3=A4sing?= Date: Mon, 30 Jul 2018 18:13:13 +0200 Subject: [PATCH] Fix PdhTest + update PdhEnumObjectItems --- .../src/com/sun/jna/platform/win32/Pdh.java | 8 +- .../com/sun/jna/platform/win32/PdhUtil.java | 170 +++++++++--------- .../com/sun/jna/platform/win32/PdhTest.java | 14 +- 3 files changed, 96 insertions(+), 96 deletions(-) diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Pdh.java b/contrib/platform/src/com/sun/jna/platform/win32/Pdh.java index f63fae7721..82d13a8e92 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/Pdh.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Pdh.java @@ -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; @@ -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) diff --git a/contrib/platform/src/com/sun/jna/platform/win32/PdhUtil.java b/contrib/platform/src/com/sun/jna/platform/win32/PdhUtil.java index 4143e41374..2664b19017 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/PdhUtil.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/PdhUtil.java @@ -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. @@ -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 @@ -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 PdhEnumObjectItemCounters(String szDataSource, String szMachineName, String szObjectName, + public static PdhEnumObjectItems PdhEnumObjectItems(String szDataSource, String szMachineName, String szObjectName, int dwDetailLevel) { List counters = new ArrayList(); + List instances = new ArrayList(); // 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 PdhEnumObjectItemInstances(String szDataSource, String szMachineName, - String szObjectName, int dwDetailLevel) { - List instances = new ArrayList(); - // 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 counters; + private final List instances; - // Can't allocate 0 memory if no instances - if (pcchInstanceListLength.getValue().intValue() < 1) { + public PdhEnumObjectItems(List counters, List instances) { + this.counters = Collections.unmodifiableList(emptyListForNullList(counters)); + this.instances = Collections.unmodifiableList(emptyListForNullList(instances)); + } + + public List getCounters() { + return counters; + } + + public List 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 emptyListForNullList (List inputList) { + if(inputList == null) { + return Collections.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 + '}'; + } + + } } diff --git a/contrib/platform/test/com/sun/jna/platform/win32/PdhTest.java b/contrib/platform/test/com/sun/jna/platform/win32/PdhTest.java index a3462c7b47..773aa9dfa2 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/PdhTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/PdhTest.java @@ -16,7 +16,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; -import java.util.List; import java.util.Map; import org.junit.Test; @@ -24,6 +23,7 @@ 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; @@ -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 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 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."); }