3030import com .sun .jna .Native ;
3131import com .sun .jna .platform .win32 .WinDef .DWORD ;
3232import com .sun .jna .platform .win32 .WinDef .DWORDByReference ;
33+ import java .util .Collections ;
3334
3435/**
3536 * Pdh utility API.
@@ -61,16 +62,23 @@ public abstract class PdhUtil {
6162 public static String PdhLookupPerfNameByIndex (String szMachineName , int dwNameIndex ) {
6263 // Call once to get required buffer size
6364 DWORDByReference pcchNameBufferSize = new DWORDByReference (new DWORD (0 ));
64- Pdh .INSTANCE .PdhLookupPerfNameByIndex (szMachineName , dwNameIndex , null , pcchNameBufferSize );
65-
65+ int result = Pdh .INSTANCE .PdhLookupPerfNameByIndex (szMachineName , dwNameIndex , null , pcchNameBufferSize );
66+ if (result != WinError .ERROR_SUCCESS && result != Pdh .PDH_MORE_DATA ) {
67+ throw new PdhException (result );
68+ }
69+
6670 // Can't allocate 0 memory
6771 if (pcchNameBufferSize .getValue ().intValue () < 1 ) {
6872 return "" ;
6973 }
7074 // Allocate buffer and call again
7175 Memory mem = new Memory (pcchNameBufferSize .getValue ().intValue () * CHAR_TO_BYTES );
72- Pdh .INSTANCE .PdhLookupPerfNameByIndex (szMachineName , dwNameIndex , mem , pcchNameBufferSize );
76+ result = Pdh .INSTANCE .PdhLookupPerfNameByIndex (szMachineName , dwNameIndex , mem , pcchNameBufferSize );
7377
78+ if (result != WinError .ERROR_SUCCESS ) {
79+ throw new PdhException (result );
80+ }
81+
7482 // Convert buffer to Java String
7583 if (CHAR_TO_BYTES == 1 ) {
7684 return mem .getString (0 );
@@ -113,9 +121,8 @@ public static int PdhLookupPerfIndexByEnglishName(String szNameBuffer) {
113121
114122 /**
115123 * Utility method to call Pdh's PdhEnumObjectItems that allocates the
116- * required memory for the mszCounterList parameter based on the type
117- * mapping used, calls to PdhEnumObjectItems, and returns the received lists
118- * of strings.
124+ * required memory for the lists parameters based on the type mapping used,
125+ * calls to PdhEnumObjectItems, and returns the received lists of strings.
119126 *
120127 * @param szDataSource
121128 * String that specifies the name of the log file used to
@@ -137,113 +144,135 @@ public static int PdhLookupPerfIndexByEnglishName(String szNameBuffer) {
137144 * returned.
138145 * @return Returns a List of Strings of the counters for the object.
139146 */
140- public static List < String > PdhEnumObjectItemCounters (String szDataSource , String szMachineName , String szObjectName ,
147+ public static PdhEnumObjectItems PdhEnumObjectItems (String szDataSource , String szMachineName , String szObjectName ,
141148 int dwDetailLevel ) {
142149 List <String > counters = new ArrayList <String >();
150+ List <String > instances = new ArrayList <String >();
143151
144152 // Call once to get string lengths
145153 DWORDByReference pcchCounterListLength = new DWORDByReference (new DWORD (0 ));
146154 DWORDByReference pcchInstanceListLength = new DWORDByReference (new DWORD (0 ));
147- Pdh .INSTANCE .PdhEnumObjectItems (szDataSource , szMachineName , szObjectName , null , pcchCounterListLength , null ,
155+ int result = Pdh .INSTANCE .PdhEnumObjectItems (szDataSource , szMachineName , szObjectName , null , pcchCounterListLength , null ,
148156 pcchInstanceListLength , dwDetailLevel , 0 );
157+ if (result != WinError .ERROR_SUCCESS && result != Pdh .PDH_MORE_DATA ) {
158+ throw new PdhException (result );
159+ }
149160
150- // Can't allocate 0 memory if no counters
151- if (pcchCounterListLength .getValue ().intValue () < 1 ) {
152- return counters ;
161+ Memory mszCounterList = null ;
162+ Memory mszInstanceList = null ;
163+
164+ if (pcchCounterListLength .getValue ().intValue () > 0 ) {
165+ mszCounterList = new Memory (pcchCounterListLength .getValue ().intValue () * CHAR_TO_BYTES );
166+ }
167+
168+ if (pcchInstanceListLength .getValue ().intValue () > 0 ) {
169+ mszInstanceList = new Memory (pcchInstanceListLength .getValue ().intValue () * CHAR_TO_BYTES );
170+ }
171+
172+ result = Pdh .INSTANCE .PdhEnumObjectItems (szDataSource , szMachineName , szObjectName , mszCounterList ,
173+ pcchCounterListLength , mszInstanceList , pcchInstanceListLength , dwDetailLevel , 0 );
174+
175+ if (result != WinError .ERROR_SUCCESS ) {
176+ throw new PdhException (result );
153177 }
154- // Allocate memory and call again to populate strings
155- Memory mszCounterList = new Memory (pcchCounterListLength .getValue ().intValue () * CHAR_TO_BYTES );
156- // Don't need the instances
157- pcchInstanceListLength .getValue ().setValue (0 );
158- Pdh .INSTANCE .PdhEnumObjectItems (szDataSource , szMachineName , szObjectName , mszCounterList ,
159- pcchCounterListLength , null , pcchInstanceListLength , dwDetailLevel , 0 );
160178
161179 // Fetch counters
162- int offset = 0 ;
163- while (offset < mszCounterList .size ()) {
164- String s = null ;
165- if (CHAR_TO_BYTES == 1 ) {
166- s = mszCounterList .getString (offset );
167- } else {
168- s = mszCounterList .getWideString (offset );
180+ if (mszCounterList != null ) {
181+ int offset = 0 ;
182+ while (offset < mszCounterList .size ()) {
183+ String s = null ;
184+ if (CHAR_TO_BYTES == 1 ) {
185+ s = mszCounterList .getString (offset );
186+ } else {
187+ s = mszCounterList .getWideString (offset );
188+ }
189+ // list ends with double null
190+ if (s .isEmpty ()) {
191+ break ;
192+ }
193+ counters .add (s );
194+ // Increment for string + null terminator
195+ offset += (s .length () + 1 ) * CHAR_TO_BYTES ;
169196 }
170- // list ends with double null
171- if (s .isEmpty ()) {
172- break ;
197+ }
198+
199+ if (mszInstanceList != null ) {
200+ int offset = 0 ;
201+ while (offset < mszInstanceList .size ()) {
202+ String s = null ;
203+ if (CHAR_TO_BYTES == 1 ) {
204+ s = mszInstanceList .getString (offset );
205+ } else {
206+ s = mszInstanceList .getWideString (offset );
207+ }
208+ // list ends with double null
209+ if (s .isEmpty ()) {
210+ break ;
211+ }
212+ instances .add (s );
213+ // Increment for string + null terminator
214+ offset += (s .length () + 1 ) * CHAR_TO_BYTES ;
173215 }
174- counters .add (s );
175- // Increment for string + null terminator
176- offset += (s .length () + 1 ) * CHAR_TO_BYTES ;
177216 }
178217
179- return counters ;
218+ return new PdhEnumObjectItems ( counters , instances ) ;
180219 }
181220
221+
182222 /**
183- * Utility method to call Pdh's PdhEnumObjectItems that allocates the
184- * required memory for the mszInstanceList parameters based on the type
185- * mapping used, calls to PdhEnumObjectItems, and returns the received lists
186- * of strings.
187- *
188- * @param szDataSource
189- * String that specifies the name of the log file used to
190- * enumerate the counter and instance names. If NULL, the
191- * function uses the computer specified in the szMachineName
192- * parameter to enumerate the names.
193- * @param szMachineName
194- * String that specifies the name of the computer that contains
195- * the counter and instance names that you want to enumerate.
196- * Include the leading slashes in the computer name, for example,
197- * \\computername. If the szDataSource parameter is NULL, you can
198- * set szMachineName to NULL to specify the local computer.
199- * @param szObjectName
200- * String that specifies the name of the object whose counter and
201- * instance names you want to enumerate.
202- * @param dwDetailLevel
203- * Detail level of the performance items to return. All items
204- * that are of the specified detail level or less will be
205- * returned.
206- * @return Returns a Lists of Strings of the instances of the object.
223+ * Holder Object for PdhEnumObjectsItems. The embedded lists are modifiable
224+ * lists and can be accessed through the {@link #getCounters()} and
225+ * {@link #getInstances()} accessors.
207226 */
208- public static List < String > PdhEnumObjectItemInstances ( String szDataSource , String szMachineName ,
209- String szObjectName , int dwDetailLevel ) {
210- List <String > instances = new ArrayList < String >() ;
227+ public static class PdhEnumObjectItems {
228+ private final List < String > counters ;
229+ private final List <String > instances ;
211230
212- // Call once to get string lengths
213- DWORDByReference pcchCounterListLength = new DWORDByReference (new DWORD (0 ));
214- DWORDByReference pcchInstanceListLength = new DWORDByReference (new DWORD (0 ));
215- Pdh .INSTANCE .PdhEnumObjectItems (szDataSource , szMachineName , szObjectName , null , pcchCounterListLength , null ,
216- pcchInstanceListLength , dwDetailLevel , 0 );
231+ public PdhEnumObjectItems (List <String > counters , List <String > instances ) {
232+ this .counters = copyAndEmptyListForNullList (counters );
233+ this .instances = copyAndEmptyListForNullList (instances );
234+ }
235+
236+ /**
237+ * @return the embedded counters list, all calls to this function receive
238+ * the same list and thus share modifications
239+ */
240+ public List <String > getCounters () {
241+ return counters ;
242+ }
217243
218- // Can't allocate 0 memory if no instances
219- if (pcchInstanceListLength .getValue ().intValue () < 1 ) {
244+ /**
245+ * @return the embedded instances list, all calls to this function receive
246+ * the same list and thus share modifications
247+ */
248+ public List <String > getInstances () {
220249 return instances ;
221250 }
222- // Allocate memory and call again to populate strings
223- Memory mszInstanceList = new Memory (pcchInstanceListLength .getValue ().intValue () * CHAR_TO_BYTES );
224- // Don't need the counters
225- pcchCounterListLength .getValue ().setValue (0 );
226- Pdh .INSTANCE .PdhEnumObjectItems (szDataSource , szMachineName , szObjectName , null , pcchCounterListLength ,
227- mszInstanceList , pcchInstanceListLength , dwDetailLevel , 0 );
228-
229- // Fetch instances
230- int offset = 0 ;
231- while (offset < mszInstanceList .size ()) {
232- String s = null ;
233- if (CHAR_TO_BYTES == 1 ) {
234- s = mszInstanceList .getString (offset );
251+
252+ private List <String > copyAndEmptyListForNullList (List <String > inputList ) {
253+ if (inputList == null ) {
254+ return new ArrayList <String >();
235255 } else {
236- s = mszInstanceList .getWideString (offset );
237- }
238- // list ends with double null
239- if (s .isEmpty ()) {
240- break ;
256+ return new ArrayList <String >(inputList );
241257 }
242- instances .add (s );
243- // Increment for string + null terminator
244- offset += (s .length () + 1 ) * CHAR_TO_BYTES ;
245258 }
246259
247- return instances ;
260+ @ Override
261+ public String toString () {
262+ return "PdhEnumObjectItems{" + "counters=" + counters + ", instances=" + instances + '}' ;
263+ }
264+ }
265+
266+ public static final class PdhException extends RuntimeException {
267+ private final int errorCode ;
268+
269+ public PdhException (int errorCode ) {
270+ super (String .format ("Pdh call failed with error code 0x%08X" , errorCode ));
271+ this .errorCode = errorCode ;
272+ }
273+
274+ public int getErrorCode () {
275+ return errorCode ;
276+ }
248277 }
249278}
0 commit comments