-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add PDH counter lookup and enumeration functions #973
Changes from 2 commits
aa8d54a
c06a68f
01aeb2a
9401f05
efcd4d3
72925a4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -277,4 +277,122 @@ public class PDH_TIME_INFO extends Structure { | |
* @see <A HREF="https://msdn.microsoft.com/en-us/library/windows/desktop/aa372677(v=vs.85).aspx">PdhSetQueryTimeRange</A> | ||
*/ | ||
int PdhSetQueryTimeRange(HANDLE hQuery, PDH_TIME_INFO pInfo); | ||
|
||
/** | ||
* Returns the specified object's counter and instance names that exist on | ||
* the specified computer or in the specified log file. | ||
* | ||
* @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 mszCounterList | ||
* Caller-allocated buffer that receives a list of | ||
* null-terminated counter names provided by the specified | ||
* object. The list contains unique counter names. The list is | ||
* terminated by two NULL characters. Set to NULL if the | ||
* pcchCounterListLengthparameter is zero. | ||
* @param pcchCounterListLength | ||
* Size of the mszCounterList buffer, in TCHARs. If zero on input | ||
* and the object exists, the function returns PDH_MORE_DATA and | ||
* sets this parameter to the required buffer size. If the buffer | ||
* is larger than the required size, the function sets this | ||
* parameter to the actual size of the buffer that was used. If | ||
* the specified size on input is greater than zero but less than | ||
* the required size, you should not rely on the returned size to | ||
* reallocate the buffer. | ||
* @param mszInstanceList | ||
* Caller-allocated buffer that receives a list of | ||
* null-terminated instance names provided by the specified | ||
* object. The list contains unique instance names. The list is | ||
* terminated by two NULL characters. Set to NULL if | ||
* pcchInstanceListLength is zero. | ||
* @param pcchInstanceListLength | ||
* Size of the mszInstanceList buffer, in TCHARs. If zero on | ||
* input and the object exists, the function returns | ||
* PDH_MORE_DATA and sets this parameter to the required buffer | ||
* size. If the buffer is larger than the required size, the | ||
* function sets this parameter to the actual size of the buffer | ||
* that was used. If the specified size on input is greater than | ||
* zero but less than the required size, you should not rely on | ||
* the returned size to reallocate the buffer. If the specified | ||
* object does not support variable instances, then the returned | ||
* value will be zero. If the specified object does support | ||
* variable instances, but does not currently have any instances, | ||
* then the value returned is 2, which is the size of an empty | ||
* MULTI_SZ list string. | ||
* @param dwDetailLevel | ||
* Detail level of the performance items to return. All items | ||
* that are of the specified detail level or less will be | ||
* returned. | ||
* @param dwFlags | ||
* This parameter must be zero. | ||
* @return If the function succeeds, it returns ERROR_SUCCESS. If the | ||
* function fails, the return value is a system error code or a PDH | ||
* error code. | ||
*/ | ||
int PdhEnumObjectItems(String szDataSource, String szMachineName, String szObjectName, char[] mszCounterList, | ||
DWORDByReference pcchCounterListLength, char[] mszInstanceList, DWORDByReference pcchInstanceListLength, | ||
int dwDetailLevel, int dwFlags); | ||
|
||
/** | ||
* | ||
* Returns the counter index corresponding to the specified counter name. | ||
* | ||
* @param szMachineName | ||
* Null-terminated string that specifies the name of the computer | ||
* where the specified counter is located. The computer name can | ||
* be specified by the DNS name or the IP address. If NULL, the | ||
* function uses the local computer. | ||
* @param szNameBuffer | ||
* Null-terminated string that contains the counter name. | ||
* @param pdwIndex | ||
* Index of the counter. | ||
* @return If the function succeeds, it returns ERROR_SUCCESS. If the | ||
* function fails, the return value is a system error code or a PDH | ||
* error code. | ||
*/ | ||
int PdhLookupPerfIndexByName(String szMachineName, String szNameBuffer, DWORDByReference pdwIndex); | ||
|
||
/** | ||
* Returns the performance object name or counter name corresponding to the | ||
* specified index. | ||
* | ||
* @param szMachineName | ||
* Null-terminated string that specifies the name of the computer | ||
* where the specified performance object or counter is located. | ||
* The computer name can be specified by the DNS name or the IP | ||
* address. If NULL, the function uses the local computer. | ||
* @param dwNameIndex | ||
* Index of the performance object or counter. | ||
* @param szNameBuffer | ||
* Caller-allocated buffer that receives the null-terminated name | ||
* of the performance object or counter. Set to NULL if | ||
* pcchNameBufferSize is zero. | ||
* @param pcchNameBufferSize | ||
* Size of the szNameBuffer buffer, in TCHARs. If zero on input, | ||
* the function returns PDH_MORE_DATA and sets this parameter to | ||
* the required buffer size. If the buffer is larger than the | ||
* required size, the function sets this parameter to the actual | ||
* size of the buffer that was used. If the specified size on | ||
* input is greater than zero but less than the required size, | ||
* you should not rely on the returned size to reallocate the | ||
* buffer. | ||
* @return If the function succeeds, it returns ERROR_SUCCESS. If the | ||
* function fails, the return value is a system error code or a PDH | ||
* error code. | ||
*/ | ||
int PdhLookupPerfNameByIndex(String szMachineName, int dwNameIndex, char[] szNameBuffer, | ||
DWORDByReference pcchNameBufferSize); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here the same as above applies. |
||
|
||
} |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -12,10 +12,14 @@ | |||
*/ | ||||
package com.sun.jna.platform.win32; | ||||
|
||||
import static org.junit.Assert.assertEquals; | ||||
import static org.junit.Assert.assertTrue; | ||||
|
||||
import java.io.PrintStream; | ||||
import java.util.Collection; | ||||
import java.util.HashMap; | ||||
import java.util.LinkedList; | ||||
import java.util.List; | ||||
import java.util.Map; | ||||
|
||||
import org.junit.Test; | ||||
|
@@ -155,4 +159,54 @@ private static String makeCounterPath(Pdh pdh, PDH_COUNTER_PATH_ELEMENTS pathEle | |||
|
||||
return Native.toString(szFullPathBuffer); | ||||
} | ||||
|
||||
@Test | ||||
public void testLookupPerfIndex() { | ||||
// Index 238 is "Processor" | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The tests are locale specific (it failed on my initial run on a german locale). Please guard the critical parts with
|
||||
int processor = 238; | ||||
String processorStr = "Processor"; | ||||
|
||||
// Test index-to-name | ||||
// Call lookup with null buffer and 0 index to get buffer size | ||||
DWORDByReference pcchNameBufferSize = new DWORDByReference(new DWORD(0)); | ||||
Pdh.INSTANCE.PdhLookupPerfNameByIndex(null, processor, null, pcchNameBufferSize); | ||||
assertTrue(pcchNameBufferSize.getValue().intValue() > 0); | ||||
// Allocate buffer and call again | ||||
char[] szNameBuffer = new char[pcchNameBufferSize.getValue().intValue()]; | ||||
Pdh.INSTANCE.PdhLookupPerfNameByIndex(null, processor, szNameBuffer, pcchNameBufferSize); | ||||
assertEquals(processorStr, Native.toString(szNameBuffer)); | ||||
|
||||
// Test name-to-index | ||||
DWORDByReference pdwIndex = new DWORDByReference(); | ||||
Pdh.INSTANCE.PdhLookupPerfIndexByName(null, processorStr, pdwIndex); | ||||
assertEquals(processor, pdwIndex.getValue().intValue()); | ||||
} | ||||
|
||||
@Test | ||||
public void testEnumObjectItems() { | ||||
String processorStr = "Processor"; | ||||
String processorTimeStr = "% Processor Time"; | ||||
|
||||
// Fetch the instance names | ||||
// Call once to get string lengths | ||||
DWORDByReference pcchCounterListLength = new DWORDByReference(new DWORD(0)); | ||||
DWORDByReference pcchInstanceListLength = new DWORDByReference(new DWORD(0)); | ||||
Pdh.INSTANCE.PdhEnumObjectItems(null, null, processorStr, null, pcchCounterListLength, null, | ||||
pcchInstanceListLength, 100, 0); | ||||
assertTrue(pcchCounterListLength.getValue().intValue() > 0); | ||||
assertTrue(pcchInstanceListLength.getValue().intValue() > 0); | ||||
// Allocate memory and call again to populate strings | ||||
char[] mszCounterList = new char[pcchCounterListLength.getValue().intValue()]; | ||||
char[] mszInstanceList = new char[pcchInstanceListLength.getValue().intValue()]; | ||||
Pdh.INSTANCE.PdhEnumObjectItems(null, null, processorStr, mszCounterList, pcchCounterListLength, | ||||
mszInstanceList, pcchInstanceListLength, 100, 0); | ||||
// Should have at least one processor and a "_Total" instance | ||||
List<String> instances = Native.toStringList(mszInstanceList); | ||||
assertTrue(instances.contains("0")); | ||||
assertTrue(instances.contains("_Total")); | ||||
// Should have a "% Processor Time" counter | ||||
List<String> counters = Native.toStringList(mszCounterList); | ||||
assertTrue(counters.contains(processorTimeStr)); | ||||
} | ||||
|
||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
char[]
parameters are problematic, as the type mapper will not change their mapping. A java char will be mapped to a wchar on the C side, but ifw32.ascii
is in effect, notLPWSTR
is required (this is awchar[]
), but aLPSTR' (a
char[]`).So what was done in other places was this: map the function with a
byte[]
as parameter and add a<Lib>Util
class, that hold a helper function, that unwraps the value correctly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there another example in the JNA project where this was done such that the Util class already exists?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a good sample:
Here is the MSDN definition
https://msdn.microsoft.com/en-us/library/windows/desktop/aa376556(v=vs.85).aspx
Binding
https://github.com/java-native-access/jna/blob/master/contrib/platform/src/com/sun/jna/platform/win32/Crypt32.java#L359
UtilHelper
https://github.com/java-native-access/jna/blob/master/contrib/platform/src/com/sun/jna/platform/win32/Crypt32Util.java#L195
psz
is anLPTSTR
so it depends on which function variant is called (CertNameToStrW
=> unicode,CertNameToStrA
=> ascii).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there are also some instances which explicitly declare both the
-A
and-W
of a function. The library invocation handler forW32API
automatically tries appending the suffix if the explicit name does not exist, but if the explicit name is used, that's what you'll get. Then you can wrap those and choose in a util wrapper.