View Javadoc
1   package org.metricshub.wmi.wbem;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * WMI Java Client
6    * ჻჻჻჻჻჻
7    * Copyright (C) 2023 - 2025 MetricsHub
8    * ჻჻჻჻჻჻
9    * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   *
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
21   */
22  
23  import com.sun.jna.Pointer;
24  import com.sun.jna.WString;
25  import com.sun.jna.platform.win32.COM.COMException;
26  import com.sun.jna.platform.win32.COM.COMUtils;
27  import com.sun.jna.platform.win32.COM.Wbemcli;
28  import com.sun.jna.platform.win32.COM.Wbemcli.IEnumWbemClassObject;
29  import com.sun.jna.platform.win32.COM.Wbemcli.IWbemClassObject;
30  import com.sun.jna.platform.win32.COM.Wbemcli.IWbemContext;
31  import com.sun.jna.platform.win32.COM.Wbemcli.IWbemLocator;
32  import com.sun.jna.platform.win32.COM.Wbemcli.IWbemServices;
33  import com.sun.jna.platform.win32.Guid.CLSID;
34  import com.sun.jna.platform.win32.Guid.GUID;
35  import com.sun.jna.platform.win32.Ole32;
36  import com.sun.jna.platform.win32.OleAuto;
37  import com.sun.jna.platform.win32.Variant;
38  import com.sun.jna.platform.win32.Variant.VARIANT;
39  import com.sun.jna.platform.win32.Variant.VARIANT.ByReference;
40  import com.sun.jna.platform.win32.WTypes;
41  import com.sun.jna.platform.win32.WTypes.BSTR;
42  import com.sun.jna.platform.win32.WinNT.HRESULT;
43  import com.sun.jna.ptr.IntByReference;
44  import com.sun.jna.ptr.PointerByReference;
45  import java.nio.charset.Charset;
46  import java.util.ArrayList;
47  import java.util.Collections;
48  import java.util.HashMap;
49  import java.util.List;
50  import java.util.Map;
51  import java.util.Set;
52  import java.util.concurrent.TimeoutException;
53  import java.util.function.Function;
54  import java.util.stream.Collectors;
55  import java.util.stream.Stream;
56  import org.metricshub.wmi.AutoCloseableReadWriteLock;
57  import org.metricshub.wmi.Utils;
58  import org.metricshub.wmi.WmiHelper;
59  import org.metricshub.wmi.WqlQuery;
60  import org.metricshub.wmi.exceptions.WmiComException;
61  import org.metricshub.wmi.exceptions.WqlQuerySyntaxException;
62  import org.metricshub.wmi.remotecommand.RemoteProcess;
63  import org.metricshub.wmi.windows.remote.WindowsRemoteCommandResult;
64  import org.metricshub.wmi.windows.remote.WindowsRemoteExecutor;
65  
66  /**
67   * Class for WBEM Services handling.
68   *
69   */
70  public class WmiWbemServices implements WindowsRemoteExecutor {
71  
72  	/**
73  	 * WMI error codes messages Map.
74  	 *
75  	 * @see <a href="https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-error-constants">WMI Error Constants</a>
76  	 */
77  	private static final Map<Long, String> MAP_HRESULT_MESSAGE;
78  
79  	static {
80  		final Map<Long, String> map = new HashMap<>();
81  		map.put(2147749889L, "WBEM_E_FAILED: Call failed. (0x80041001)");
82  		map.put(2147749890L, "WBEM_E_NOT_FOUND: Object cannot be found. (0x80041002)");
83  		map.put(
84  			2147749891L,
85  			"WBEM_E_ACCESS_DENIED: Current user does not have permission to perform the action. (0x80041003)"
86  		);
87  		map.put(
88  			2147749892L,
89  			"WBEM_E_PROVIDER_FAILURE: Provider has failed at some time other than during initialization. (0x80041004)"
90  		);
91  		map.put(2147749893L, "WBEM_E_TYPE_MISMATCH: Type mismatch occurred. (0x80041005)");
92  		map.put(2147749894L, "WBEM_E_OUT_OF_MEMORY: Not enough memory for the operation. (0x80041006)");
93  		map.put(2147749895L, "WBEM_E_INVALID_CONTEXT: The IWbemContext object is not valid. (0x80041007)");
94  		map.put(2147749896L, "WBEM_E_INVALID_PARAMETER: One of the parameters to the call is not correct. (0x80041008)");
95  		map.put(
96  			2147749897L,
97  			"WBEM_E_NOT_AVAILABLE: Resource, typically a remote server, is not currently available. (0x80041009)"
98  		);
99  		map.put(
100 			2147749898L,
101 			"WBEM_E_CRITICAL_ERROR: Internal, critical, and unexpected error occurred. Report the error to Microsoft Technical Support. (0x8004100A)"
102 		);
103 		map.put(
104 			2147749899L,
105 			"WBEM_E_INVALID_STREAM: One or more network packets were corrupted during a remote session. (0x8004100B)"
106 		);
107 		map.put(2147749900L, "WBEM_E_NOT_SUPPORTED: Feature or operation is not supported. (0x8004100C)");
108 		map.put(2147749901L, "WBEM_E_INVALID_SUPERCLASS: Parent class specified is not valid. (0x8004100D)");
109 		map.put(2147749902L, "WBEM_E_INVALID_NAMESPACE: Namespace specified cannot be found. (0x8004100E)");
110 		map.put(2147749903L, "WBEM_E_INVALID_OBJECT: Specified instance is not valid. (0x8004100F)");
111 		map.put(2147749904L, "WBEM_E_INVALID_CLASS: Specified class is not valid. (0x80041010)");
112 		map.put(
113 			2147749905L,
114 			"WBEM_E_PROVIDER_NOT_FOUND: Provider referenced in the schema does not have a corresponding registration. (0x80041011)"
115 		);
116 		map.put(
117 			2147749906L,
118 			"WBEM_E_INVALID_PROVIDER_REGISTRATION: Provider referenced in the schema has an incorrect or incomplete registration. (0x80041012)"
119 		);
120 		map.put(
121 			2147749907L,
122 			"WBEM_E_PROVIDER_LOAD_FAILURE: COM cannot locate a provider referenced in the schema. (0x80041013)"
123 		);
124 		map.put(
125 			2147749908L,
126 			"WBEM_E_INITIALIZATION_FAILURE: Component, such as a provider, failed to initialize for internal reasons. (0x80041014)"
127 		);
128 		map.put(
129 			2147749909L,
130 			"WBEM_E_TRANSPORT_FAILURE: Networking error that prevents normal operation has occurred. (0x80041015)"
131 		);
132 		map.put(
133 			2147749910L,
134 			"WBEM_E_INVALID_OPERATION: Requested operation is not valid. This error usually applies to invalid attempts to delete classes or properties. (0x80041016)"
135 		);
136 		map.put(2147749911L, "WBEM_E_INVALID_QUERY: Query was not syntactically valid. (0x80041017)");
137 		map.put(2147749912L, "WBEM_E_INVALID_QUERY_TYPE: Requested query language is not supported. (0x80041018)");
138 		map.put(
139 			2147749913L,
140 			"WBEM_E_ALREADY_EXISTS: In a put operation, the wbemChangeFlagCreateOnly flag was specified, but the instance already exists. (0x80041019)"
141 		);
142 		map.put(
143 			2147749914L,
144 			"WBEM_E_OVERRIDE_NOT_ALLOWED: Not possible to perform the add operation on this qualifier because the owning object does not permit overrides. (0x8004101A)"
145 		);
146 		map.put(
147 			2147749915L,
148 			"WBEM_E_PROPAGATED_QUALIFIER: User attempted to delete a qualifier that was not owned. The qualifier was inherited from a parent class. (0x8004101B)"
149 		);
150 		map.put(
151 			2147749916L,
152 			"WBEM_E_PROPAGATED_PROPERTY: User attempted to delete a property that was not owned. The property was inherited from a parent class. (0x8004101C)"
153 		);
154 		map.put(
155 			2147749917L,
156 			"WBEM_E_UNEXPECTED: Client made an unexpected and illegal sequence of calls, such as calling EndEnumeration before calling BeginEnumeration. (0x8004101D)"
157 		);
158 		map.put(
159 			2147749918L,
160 			"WBEM_E_ILLEGAL_OPERATION: User requested an illegal operation, such as spawning a class from an instance. (0x8004101E)"
161 		);
162 		map.put(
163 			2147749919L,
164 			"WBEM_E_CANNOT_BE_KEY: Illegal attempt to specify a key qualifier on a" +
165 			" property that cannot be a key. The keys are specified in the class " +
166 			"definition for an object and cannot be altered on a per-instance basis. " +
167 			"(0x8004101F)"
168 		);
169 		map.put(
170 			2147749920L,
171 			"WBEM_E_INCOMPLETE_CLASS: Current object is not a valid class definition. " +
172 			"Either it is incomplete or it has not been registered with WMI using SWbemObject." +
173 			"Put_. (0x80041020)"
174 		);
175 		map.put(2147749921L, "WBEM_E_INVALID_SYNTAX: Query is syntactically not valid. (0x80041021)");
176 		map.put(2147749922L, "WBEM_E_NONDECORATED_OBJECT: Reserved for future use. (0x80041022)");
177 		map.put(2147749923L, "WBEM_E_READ_ONLY: An attempt was made to modify a read-only property. (0x80041023)");
178 		map.put(
179 			2147749924L,
180 			"WBEM_E_PROVIDER_NOT_CAPABLE: Provider cannot perform the requested operation. " +
181 			"This can include a query that is too complex, retrieving an instance, creating or " +
182 			"updating a class, deleting a class, or enumerating a class. (0x80041024)"
183 		);
184 		map.put(
185 			2147749925L,
186 			"WBEM_E_CLASS_HAS_CHILDREN: Attempt was made to make a change that invalidates a subclass. (0x80041025)"
187 		);
188 		map.put(
189 			2147749926L,
190 			"WBEM_E_CLASS_HAS_INSTANCES: Attempt was made to delete or modify a class that has instances. (0x80041026)"
191 		);
192 		map.put(2147749927L, "WBEM_E_QUERY_NOT_IMPLEMENTED: Reserved for future use. (0x80041027)");
193 		map.put(
194 			2147749928L,
195 			"WBEM_E_ILLEGAL_NULL: Value of Nothing/NULL was specified for a property " +
196 			"that must have a value, such as one " +
197 			"that is marked by a Key, Indexed, or Not_Null qualifier. (0x80041028)"
198 		);
199 		map.put(
200 			2147749929L,
201 			"WBEM_E_INVALID_QUALIFIER_TYPE: Variant value for a qualifier was provided that is not a legal qualifier type. (0x80041029)"
202 		);
203 		map.put(2147749930L, "WBEM_E_INVALID_PROPERTY_TYPE: CIM type specified for a property is not valid. (0x8004102A)");
204 		map.put(
205 			2147749931L,
206 			"WBEM_E_VALUE_OUT_OF_RANGE: Request was made with an out-of-range value or it is incompatible with the type. (0x8004102B)"
207 		);
208 		map.put(
209 			2147749932L,
210 			"WBEM_E_CANNOT_BE_SINGLETON: Illegal attempt was made to make a class singleton, such as when the class is derived from a non-singleton class. (0x8004102C)"
211 		);
212 		map.put(2147749933L, "WBEM_E_INVALID_CIM_TYPE: CIM type specified is not valid. (0x8004102D)");
213 		map.put(2147749934L, "WBEM_E_INVALID_METHOD: Requested method is not available. (0x8004102E)");
214 		map.put(
215 			2147749935L,
216 			"WBEM_E_INVALID_METHOD_PARAMETERS: Parameters provided for the method are not valid. (0x8004102F)"
217 		);
218 		map.put(
219 			2147749936L,
220 			"WBEM_E_SYSTEM_PROPERTY: There was an attempt to get qualifiers on a system property. (0x80041030)"
221 		);
222 		map.put(2147749937L, "WBEM_E_INVALID_PROPERTY: Property type is not recognized. (0x80041031)");
223 		map.put(
224 			2147749938L,
225 			"WBEM_E_CALL_CANCELLED: Asynchronous process has been canceled internally or by the user." +
226 			" Note that due to the timing and nature of the asynchronous operation, the operation may " +
227 			"not have been truly canceled. (0x80041032)"
228 		);
229 		map.put(
230 			2147749939L,
231 			"WBEM_E_SHUTTING_DOWN: User has requested an operation while WMI is in the process of shutting down. (0x80041033)"
232 		);
233 		map.put(
234 			2147749940L,
235 			"WBEM_E_PROPAGATED_METHOD: Attempt was made to reuse an existing method name from a parent class and the signatures do not match. (0x80041034)"
236 		);
237 		map.put(
238 			2147749941L,
239 			"WBEM_E_UNSUPPORTED_PARAMETER: One or more parameter values, such as a " +
240 			"query text, is too complex or unsupported. WMI is therefore requested " +
241 			"to retry the operation with simpler parameters. (0x80041035)"
242 		);
243 		map.put(2147749942L, "WBEM_E_MISSING_PARAMETER_ID: Parameter was missing from the method call. (0x80041036)");
244 		map.put(
245 			2147749943L,
246 			"WBEM_E_INVALID_PARAMETER_ID: Method parameter has an ID qualifier that is not valid. (0x80041037)"
247 		);
248 		map.put(
249 			2147749944L,
250 			"WBEM_E_NONCONSECUTIVE_PARAMETER_IDS: One or more of the method parameters have ID qualifiers that are out of sequence. (0x80041038)"
251 		);
252 		map.put(2147749945L, "WBEM_E_PARAMETER_ID_ON_RETVAL: Return value for a method has an ID qualifier. (0x80041039)");
253 		map.put(2147749946L, "WBEM_E_INVALID_OBJECT_PATH: Specified object path was not valid. (0x8004103A)");
254 		map.put(
255 			2147749947L,
256 			"WBEM_E_OUT_OF_DISK_SPACE: Disk is out of space or the 4 GB limit on WMI repository (CIM repository) size is reached. (0x8004103B)"
257 		);
258 		map.put(
259 			2147749948L,
260 			"WBEM_E_BUFFER_TOO_SMALL: Supplied buffer was too small to hold all of the objects in the enumerator or to read a string property. (0x8004103C)"
261 		);
262 		map.put(
263 			2147749949L,
264 			"WBEM_E_UNSUPPORTED_PUT_EXTENSION: Provider does not support the requested put operation. (0x8004103D)"
265 		);
266 		map.put(
267 			2147749950L,
268 			"WBEM_E_UNKNOWN_OBJECT_TYPE: Object with an incorrect type or version was encountered during marshaling. (0x8004103E)"
269 		);
270 		map.put(
271 			2147749951L,
272 			"WBEM_E_UNKNOWN_PACKET_TYPE: Packet with an incorrect type or version was encountered during marshaling. (0x8004103F)"
273 		);
274 		map.put(2147749952L, "WBEM_E_MARSHAL_VERSION_MISMATCH: Packet has an unsupported version. (0x80041040)");
275 		map.put(2147749953L, "WBEM_E_MARSHAL_INVALID_SIGNATURE: Packet appears to be corrupt. (0x80041041)");
276 		map.put(
277 			2147749954L,
278 			"WBEM_E_INVALID_QUALIFIER: Attempt was made to mismatch qualifiers, such as putting [key] on an object instead of a property. (0x80041042)"
279 		);
280 		map.put(
281 			2147749955L,
282 			"WBEM_E_INVALID_DUPLICATE_PARAMETER: Duplicate parameter was declared in a CIM method. (0x80041043)"
283 		);
284 		map.put(2147749956L, "WBEM_E_TOO_MUCH_DATA: Reserved for future use. (0x80041044)");
285 		map.put(
286 			2147749957L,
287 			"WBEM_E_SERVER_TOO_BUSY: Call to IWbemObjectSink::Indicate has failed. The provider can refire the event. (0x80041045)"
288 		);
289 		map.put(2147749958L, "WBEM_E_INVALID_FLAVOR: Specified qualifier flavor was not valid. (0x80041046)");
290 		map.put(
291 			2147749959L,
292 			"WBEM_E_CIRCULAR_REFERENCE: Attempt was made to create a reference that is circular (for example, deriving a class from itself). (0x80041047)"
293 		);
294 		map.put(2147749960L, "WBEM_E_UNSUPPORTED_CLASS_UPDATE: Specified class is not supported. (0x80041048)");
295 		map.put(
296 			2147749961L,
297 			"WBEM_E_CANNOT_CHANGE_KEY_INHERITANCE: Attempt was made to change a key when instances or subclasses are already using the key. (0x80041049)"
298 		);
299 		map.put(
300 			2147749968L,
301 			"WBEM_E_CANNOT_CHANGE_INDEX_INHERITANCE: An attempt was made to change an index when instances or subclasses are already using the index. (0x80041050)"
302 		);
303 		map.put(
304 			2147749969L,
305 			"WBEM_E_TOO_MANY_PROPERTIES: Attempt was made to create more properties than the current version of the class supports. (0x80041051)"
306 		);
307 		map.put(
308 			2147749970L,
309 			"WBEM_E_UPDATE_TYPE_MISMATCH: Property was redefined with a conflicting type in a derived class. (0x80041052)"
310 		);
311 		map.put(
312 			2147749971L,
313 			"WBEM_E_UPDATE_OVERRIDE_NOT_ALLOWED: Attempt was made in a derived class to override a qualifier that cannot be overridden. (0x80041053)"
314 		);
315 		map.put(
316 			2147749972L,
317 			"WBEM_E_UPDATE_PROPAGATED_METHOD: Method was re-declared with a conflicting signature in a derived class. (0x80041054)"
318 		);
319 		map.put(
320 			2147749973L,
321 			"WBEM_E_METHOD_NOT_IMPLEMENTED: Attempt was made to execute a method not marked with [implemented] in any relevant class. (0x80041055)"
322 		);
323 		map.put(
324 			2147749974L,
325 			"WBEM_E_METHOD_DISABLED: Attempt was made to execute a method marked with [disabled]. (0x80041056)"
326 		);
327 		map.put(2147749975L, "WBEM_E_REFRESHER_BUSY: Refresher is busy with another operation. (0x80041057)");
328 		map.put(2147749976L, "WBEM_E_UNPARSABLE_QUERY: Filtering query is syntactically not valid. (0x80041058)");
329 		map.put(
330 			2147749977L,
331 			"WBEM_E_NOT_EVENT_CLASS: The FROM clause of a filtering query references a class that is not an event class (not derived from __Event). (0x80041059)"
332 		);
333 		map.put(
334 			2147749978L,
335 			"WBEM_E_MISSING_GROUP_WITHIN: A GROUP BY clause was used without the corresponding GROUP WITHIN clause. (0x8004105A)"
336 		);
337 		map.put(
338 			2147749979L,
339 			"WBEM_E_MISSING_AGGREGATION_LIST: A GROUP BY clause was used. Aggregation on all properties is not supported. (0x8004105B)"
340 		);
341 		map.put(
342 			2147749980L,
343 			"WBEM_E_PROPERTY_NOT_AN_OBJECT: Dot notation was used on a property that is not an embedded object. (0x8004105C)"
344 		);
345 		map.put(
346 			2147749981L,
347 			"WBEM_E_AGGREGATING_BY_OBJECT: A GROUP BY clause references a property that is an embedded object without using dot notation. (0x8004105D)"
348 		);
349 		map.put(
350 			2147749983L,
351 			"WBEM_E_UNINTERPRETABLE_PROVIDER_QUERY: Event provider registration " +
352 			"query (__EventProviderRegistration) did not specify the classes " +
353 			"for which events were provided. (0x8004105F)"
354 		);
355 		map.put(
356 			2147749984L,
357 			"WBEM_E_BACKUP_RESTORE_WINMGMT_RUNNING: Request was made to back up " +
358 			"or restore the repository while it was in use by WinMgmt.exe, " +
359 			"or by the SVCHOST process that contains the WMI service. (0x80041060)"
360 		);
361 		map.put(
362 			2147749985L,
363 			"WBEM_E_QUEUE_OVERFLOW: Asynchronous delivery queue overflowed from the event consumer being too slow. (0x80041061)"
364 		);
365 		map.put(
366 			2147749986L,
367 			"WBEM_E_PRIVILEGE_NOT_HELD: Operation failed because the client did not have the necessary security privilege. (0x80041062)"
368 		);
369 		map.put(2147749987L, "WBEM_E_INVALID_OPERATOR: Operator is not valid for this property type. (0x80041063)");
370 		map.put(
371 			2147749988L,
372 			"WBEM_E_LOCAL_CREDENTIALS: User specified a username/password/authority on a local connection. " +
373 			"The user must use a blank username/password and rely on default security. (0x80041064)"
374 		);
375 		map.put(
376 			2147749989L,
377 			"WBEM_E_CANNOT_BE_ABSTRACT: Class was made abstract when its parent class is not abstract. (0x80041065)"
378 		);
379 		map.put(
380 			2147749990L,
381 			"WBEM_E_AMENDED_OBJECT: Amended object was written without the WBEM_FLAG_USE_AMENDED_QUALIFIERS flag being specified. (0x80041066)"
382 		);
383 		map.put(
384 			2147749991L,
385 			"WBEM_E_CLIENT_TOO_SLOW: Client did not retrieve objects quickly enough from an enumeration. " +
386 			"This constant is returned when a client creates an enumeration object, but does not retrieve " +
387 			"objects from the enumerator in a timely fashion, causing the enumerator's object caches to back up. (0x80041067)"
388 		);
389 		map.put(2147749992L, "WBEM_E_NULL_SECURITY_DESCRIPTOR: Null security descriptor was used. (0x80041068)");
390 		map.put(2147749993L, "WBEM_E_TIMED_OUT: Operation timed out. (0x80041069)");
391 		map.put(2147749994L, "WBEM_E_INVALID_ASSOCIATION: Association is not valid. (0x8004106A)");
392 		map.put(2147749995L, "WBEM_E_AMBIGUOUS_OPERATION: Operation was ambiguous. (0x8004106B)");
393 		map.put(
394 			2147749996L,
395 			"WBEM_E_QUOTA_VIOLATION: WMI is taking up too much memory. This can be caused by low memory availability or excessive memory consumption by WMI. (0x8004106C)"
396 		);
397 		map.put(2147749997L, "WBEM_E_TRANSACTION_CONFLICT: Operation resulted in a transaction conflict. (0x8004106D)");
398 		map.put(2147749998L, "WBEM_E_FORCED_ROLLBACK: Transaction forced a rollback. (0x8004106E)");
399 		map.put(2147749999L, "WBEM_E_UNSUPPORTED_LOCALE: Locale used in the call is not supported. (0x8004106F)");
400 		map.put(2147750000L, "WBEM_E_HANDLE_OUT_OF_DATE: Object handle is out-of-date. (0x80041070)");
401 		map.put(2147750001L, "WBEM_E_CONNECTION_FAILED: Connection to the SQL database failed. (0x80041071)");
402 		map.put(2147750002L, "WBEM_E_INVALID_HANDLE_REQUEST: Handle request was not valid. (0x80041072)");
403 		map.put(
404 			2147750003L,
405 			"WBEM_E_PROPERTY_NAME_TOO_WIDE: Property name contains more than 255 characters. (0x80041073)"
406 		);
407 		map.put(2147750004L, "WBEM_E_CLASS_NAME_TOO_WIDE: Class name contains more than 255 characters. (0x80041074)");
408 		map.put(2147750005L, "WBEM_E_METHOD_NAME_TOO_WIDE: Method name contains more than 255 characters. (0x80041075)");
409 		map.put(
410 			2147750006L,
411 			"WBEM_E_QUALIFIER_NAME_TOO_WIDE: Qualifier name contains more than 255 characters. (0x80041076)"
412 		);
413 		map.put(
414 			2147750007L,
415 			"WBEM_E_RERUN_COMMAND: The SQL command must be rerun because there is a deadlock in SQL. This can be returned only when data is being stored in an SQL database. (0x80041077)"
416 		);
417 		map.put(
418 			2147750008L,
419 			"WBEM_E_DATABASE_VER_MISMATCH: The database version does not match the version that the repository driver processes. (0x80041078)"
420 		);
421 		map.put(
422 			2147750009L,
423 			"WBEM_E_VETO_DELETE: WMI cannot execute the delete operation because the provider does not allow it. (0x80041079)"
424 		);
425 		map.put(
426 			2147750010L,
427 			"WBEM_E_VETO_PUT: WMI cannot execute the put operation because the provider does not allow it. (0x8004107A)"
428 		);
429 		map.put(
430 			2147750016L,
431 			"WBEM_E_INVALID_LOCALE: Specified locale identifier was not valid for the operation. (0x80041080)"
432 		);
433 		map.put(2147750017L, "WBEM_E_PROVIDER_SUSPENDED: Provider is suspended. (0x80041081)");
434 		map.put(
435 			2147750018L,
436 			"WBEM_E_SYNCHRONIZATION_REQUIRED: Object must be written to the WMI repository and retrieved again before the requested operation can succeed." +
437 			" This constant is returned when an object must be committed and retrieved to see the property value. (0x80041082)"
438 		);
439 		map.put(2147750019L, "WBEM_E_NO_SCHEMA: Operation cannot be completed; no schema is available. (0x80041083)");
440 		map.put(
441 			2147750020L,
442 			"WBEM_E_PROVIDER_ALREADY_REGISTERED: Provider cannot be registered because it is already registered. (0x119FD010)"
443 		);
444 		map.put(2147750021L, "WBEM_E_PROVIDER_NOT_REGISTERED: Provider was not registered. (0x80041085)");
445 		map.put(2147750022L, "WBEM_E_FATAL_TRANSPORT_ERROR: A fatal transport error occurred. (0x80041086)");
446 		map.put(
447 			2147750023L,
448 			"WBEM_E_ENCRYPTED_CONNECTION_REQUIRED: User attempted to set a computer name or domain without an encrypted connection. (0x80041087)"
449 		);
450 		map.put(
451 			2147750024L,
452 			"WBEM_E_PROVIDER_TIMED_OUT: A provider failed to report results within the specified timeout. (0x80041088)"
453 		);
454 		map.put(2147750025L, "WBEM_E_NO_KEY: User attempted to put an instance with no defined key. (0x80041089)");
455 		map.put(
456 			2147750026L,
457 			"WBEM_E_PROVIDER_DISABLED: User attempted to register a provider instance but the COM server for the provider instance was unloaded. (0x8004108A)"
458 		);
459 		map.put(
460 			2147753985L,
461 			"WBEMESS_E_REGISTRATION_TOO_BROAD: Provider registration overlaps with the system event domain. (0x80042001)"
462 		);
463 		map.put(
464 			2147753986L,
465 			"WBEMESS_E_REGISTRATION_TOO_PRECISE: A WITHIN clause was not used in this query. (0x80042002)"
466 		);
467 		map.put(
468 			2147753987L,
469 			"WBEMESS_E_AUTHZ_NOT_PRIVILEGED: This computer does not have the necessary domain permissions " +
470 			"to support the security functions that relate to the created subscription instance. Contact the " +
471 			"Domain Administrator to get this computer added to the Windows Authorization Access Group. (0x80042003)"
472 		);
473 		map.put(2147758081L, "WBEM_E_RETRY_LATER: Reserved for future use. (0x80043001)");
474 		map.put(2147758082L, "WBEM_E_RESOURCE_CONTENTION: Reserved for future use. (0x80043002)");
475 		map.put(2147762177L, "WBEMMOF_E_EXPECTED_QUALIFIER_NAME: Expected a qualifier name. (0x80044001)");
476 		map.put(2147762178L, "WBEMMOF_E_EXPECTED_SEMI: Expected semicolon or '='. (0x80044002)");
477 		map.put(2147762179L, "WBEMMOF_E_EXPECTED_OPEN_BRACE: Expected an opening brace. (0x80044003)");
478 		map.put(
479 			2147762180L,
480 			"WBEMMOF_E_EXPECTED_CLOSE_BRACE: Missing closing brace or an illegal array element (0x80044004)"
481 		);
482 		map.put(2147762181L, "WBEMMOF_E_EXPECTED_CLOSE_BRACKET: Expected a closing bracket. (0x80044005)");
483 		map.put(2147762182L, "WBEMMOF_E_EXPECTED_CLOSE_PAREN: Expected closing parenthesis. (0x80044006)");
484 		map.put(
485 			2147762183L,
486 			"WBEMMOF_E_ILLEGAL_CONSTANT_VALUE: Numeric value out of range or strings without quotes. (0x80044007)"
487 		);
488 		map.put(2147762184L, "WBEMMOF_E_EXPECTED_TYPE_IDENTIFIER: Expected a type identifiers. (0x80044008)");
489 		map.put(2147762185L, "WBEMMOF_E_EXPECTED_OPEN_PAREN: Expected an open parenthesis. (0x80044009)");
490 		map.put(2147762186L, "WBEMMOF_E_UNRECOGNIZED_TOKEN: Unexpected token in the file. (0x8004400A)");
491 		map.put(2147762187L, "WBEMMOF_E_UNRECOGNIZED_TYPE: Unrecognized or unsupported type identifier. (0x8004400B)");
492 		map.put(2147762188L, "WBEMMOF_E_EXPECTED_PROPERTY_NAME: Expected property or method name. (0x8004400C)");
493 		map.put(
494 			2147762189L,
495 			"WBEMMOF_E_TYPEDEF_NOT_SUPPORTED: Typedefs and enumerated types are not supported. (0x8004400D)"
496 		);
497 		map.put(
498 			2147762190L,
499 			"WBEMMOF_E_UNEXPECTED_ALIAS: Only a reference to a class object can have an alias value. (0x8004400E)"
500 		);
501 		map.put(
502 			2147762191L,
503 			"WBEMMOF_E_UNEXPECTED_ARRAY_INIT: Unexpected array initialization. Arrays must be declared with []. (0x8004400F)"
504 		);
505 		map.put(2147762192L, "WBEMMOF_E_INVALID_AMENDMENT_SYNTAX: Namespace path syntax is not valid. (0x80044010)");
506 		map.put(2147762193L, "WBEMMOF_E_INVALID_DUPLICATE_AMENDMENT: Duplicate amendment specifiers. (0x80044011)");
507 		map.put(2147762194L, "WBEMMOF_E_INVALID_PRAGMA: #pragma must be followed by a valid keyword. (0x80044012)");
508 		map.put(2147762195L, "WBEMMOF_E_INVALID_NAMESPACE_SYNTAX: Namespace path syntax is not valid. (0x80044013)");
509 		map.put(
510 			2147762196L,
511 			"WBEMMOF_E_EXPECTED_CLASS_NAME: Unexpected character in class name must be an identifier. (0x80044014)"
512 		);
513 		map.put(
514 			2147762197L,
515 			"WBEMMOF_E_TYPE_MISMATCH: The value specified cannot be made into the appropriate type. (0x80044015)"
516 		);
517 		map.put(
518 			2147762198L,
519 			"WBEMMOF_E_EXPECTED_ALIAS_NAME: Dollar sign must be followed by an alias name as an identifier. (0x80044016)"
520 		);
521 		map.put(2147762199L, "WBEMMOF_E_INVALID_CLASS_DECLARATION: Class declaration is not valid. (0x80044017)");
522 		map.put(
523 			2147762200L,
524 			"WBEMMOF_E_INVALID_INSTANCE_DECLARATION: The instance declaration is not valid. It must start with \"instance of\". (0x80044018)"
525 		);
526 		map.put(
527 			2147762201L,
528 			"WBEMMOF_E_EXPECTED_DOLLAR: Expected dollar sign. An alias in the form \"$name\" must follow the \"as\" keyword. (0x80044019)"
529 		);
530 		map.put(
531 			2147762202L,
532 			"WBEMMOF_E_CIMTYPE_QUALIFIER: \"CIMTYPE\" qualifier cannot be specified directly in a MOF file. Use standard type notation. (0x8004401A)"
533 		);
534 		map.put(2147762203L, "WBEMMOF_E_DUPLICATE_PROPERTY: Duplicate property name was found in the MOF. (0x8004401B)");
535 		map.put(
536 			2147762204L,
537 			"WBEMMOF_E_INVALID_NAMESPACE_SPECIFICATION: Namespace syntax is not valid. References to other servers are not allowed. (0x8004401C)"
538 		);
539 		map.put(2147762205L, "WBEMMOF_E_OUT_OF_RANGE: Value out of range. (0x8004401D)");
540 		map.put(
541 			2147762206L,
542 			"WBEMMOF_E_INVALID_FILE: The file is not a valid text MOF file or binary MOF file. (0x8004401E)"
543 		);
544 		map.put(2147762207L, "WBEMMOF_E_ALIASES_IN_EMBEDDED: Embedded objects cannot be aliases. (0x8004401F)");
545 		map.put(2147762208L, "WBEMMOF_E_NULL_ARRAY_ELEM: NULL elements in an array are not supported. (0x80044020)");
546 		map.put(
547 			2147762209L,
548 			"WBEMMOF_E_DUPLICATE_QUALIFIER: Qualifier was used more than once on the object. (0x80044021)"
549 		);
550 		map.put(
551 			2147762210L,
552 			"WBEMMOF_E_EXPECTED_FLAVOR_TYPE: Expected a flavor type such as ToInstance, ToSubClass, EnableOverride, or DisableOverride. (0x80044022)"
553 		);
554 		map.put(
555 			2147762211L,
556 			"WBEMMOF_E_INCOMPATIBLE_FLAVOR_TYPES: Combining EnableOverride and DisableOverride on same qualifier is not legal. (0x80044023)"
557 		);
558 		map.put(2147762212L, "WBEMMOF_E_MULTIPLE_ALIASES: An alias cannot be used twice. (0x80044024)");
559 		map.put(
560 			2147762213L,
561 			"WBEMMOF_E_INCOMPATIBLE_FLAVOR_TYPES2: Combining Restricted, and ToInstance or ToSubClass is not legal. (0x80044025)"
562 		);
563 		map.put(2147762214L, "WBEMMOF_E_NO_ARRAYS_RETURNED: Methods cannot return array values. (0x80044026)");
564 		map.put(2147762215L, "WBEMMOF_E_MUST_BE_IN_OR_OUT: Arguments must have an In or Out qualifier. (0x80044027)");
565 		map.put(2147762216L, "WBEMMOF_E_INVALID_FLAGS_SYNTAX: Flags syntax is not valid. (0x80044028)");
566 		map.put(
567 			2147762217L,
568 			"WBEMMOF_E_EXPECTED_BRACE_OR_BAD_TYPE: The final brace and semi-colon for a class are missing. (0x80044029)"
569 		);
570 		map.put(
571 			2147762218L,
572 			"WBEMMOF_E_UNSUPPORTED_CIMV22_QUAL_VALUE: A CIM version 2.2 feature is not supported for a qualifier value. (0x8004402A)"
573 		);
574 		map.put(
575 			2147762219L,
576 			"WBEMMOF_E_UNSUPPORTED_CIMV22_DATA_TYPE: The CIM version 2.2 data type is not supported. (0x8004402B)"
577 		);
578 		map.put(
579 			2147762220L,
580 			"WBEMMOF_E_INVALID_DELETEINSTANCE_SYNTAX: The delete instance syntax is not valid. It should be #pragma DeleteInstance(\"instancepath\", FAIL|NOFAIL). (0x8004402C)"
581 		);
582 		map.put(
583 			2147762221L,
584 			"WBEMMOF_E_INVALID_QUALIFIER_SYNTAX: The qualifier syntax is not valid. It should be qualifiername:type=value,scope(class|instance), flavorname. (0x8004402D)"
585 		);
586 		map.put(
587 			2147762222L,
588 			"WBEMMOF_E_QUALIFIER_USED_OUTSIDE_SCOPE: The qualifier is used outside of its scope. (0x8004402E)"
589 		);
590 		map.put(
591 			2147762223L,
592 			"WBEMMOF_E_ERROR_CREATING_TEMP_FILE: Error creating temporary file. The temporary file is an intermediate stage in the MOF compilation. (0x8004402F)"
593 		);
594 		map.put(
595 			2147762224L,
596 			"WBEMMOF_E_ERROR_INVALID_INCLUDE_FILE: A file included in the MOF by the preprocessor command #include is not valid. (0x80044030)"
597 		);
598 		map.put(
599 			2147762225L,
600 			"WBEMMOF_E_INVALID_DELETECLASS_SYNTAX: The syntax for the preprocessor commands #pragma deleteinstance or #pragma deleteclass is not valid. (0x80044031)"
601 		);
602 		MAP_HRESULT_MESSAGE = Collections.unmodifiableMap(map);
603 	}
604 
605 	/**
606 	 * <p>Check if the result.</p>
607 	 * <p>If the result is failed, throw a COMException.</p>
608 	 *
609 	 * @param hResult The result to check.
610 	 * @param message The error message if result failed.
611 	 * @throws WmiComException For any problem encountered with JNA.
612 	 */
613 	static void checkHResult(final HRESULT hResult, final String message) throws WmiComException {
614 		Utils.checkNonNull(hResult, "hResult");
615 		if (COMUtils.FAILED(hResult)) {
616 			throw new WmiComException("%s. %s", message, getWmiComErrorMessage(hResult));
617 		}
618 	}
619 
620 	/**
621 	 * Get the message from the error code.
622 	 *
623 	 * @param hResult The result
624 	 * @return The error code message or juste the error code if unknown.
625 	 */
626 	static String getWmiComErrorMessage(final HRESULT hResult) {
627 		final int code = hResult.intValue();
628 		return MAP_HRESULT_MESSAGE.getOrDefault(
629 			Integer.toUnsignedLong(code),
630 			String.format("code: 0x%s.", Integer.toHexString(code))
631 		);
632 	}
633 
634 	/**
635 	 * IWbemContext unmarshaler Class Identifier CLSID.
636 	 *
637 	 *  @see <a href="https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wmi/18c8f1a1-652f-43b7-9186-6098bc303a8d">2.2.13 IWbemContext Interface</a>
638 	 */
639 	private static final CLSID CLSID_WBEM_CONTEXT = new CLSID("674B6698-EE92-11D0-AD71-00C04FD8FDFF");
640 
641 	/**
642 	 * IWbemContext Interface Universally Unique Identifier UUID.
643 	 *
644 	 *  @see <a href="https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wmi/18c8f1a1-652f-43b7-9186-6098bc303a8d">2.2.13 IWbemContext Interface</a>
645 	 */
646 	private static final GUID IID_WBEM_CONTEXT = new GUID("44ACA674-E8FC-11D0-A07C-00C04FB68820");
647 
648 	/** WbemContext property for Provider Architecture */
649 	private static final String WBEMCONTEXT_NAME_FOR_PROVIDER_ARCHITECTURE = "__ProviderArchitecture";
650 
651 	private static final int SET_VALUE_FUNCTION_VTABLE_ID_IN_WBEM_CONTEXT_INTERFACE = 8;
652 
653 	private static final int WBEM_SERVICES_GET_OBJECT_VTABLE_ID = 6;
654 	private static final int WBEM_SERVICES_EXEC_METHOD_VTABLE_ID = 24;
655 
656 	private static final int WBEM_CLASS_OBJECT_PUT_VTABLE_ID = 5;
657 	private static final int WBEM_CLASS_OBJECT_SPAWN_INSTANCE_VTABLE_ID = 15;
658 	private static final int WBEM_CLASS_OBJECT_GET_METHOD_VTABLE_ID = 19;
659 
660 	/**
661 	 * This flag makes the operation synchronous. This is the default behavior and so this flag need not be explicitly specified.
662 	 *
663 	 *  @see <a href="https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wmi/2bbdf995-93d8-4902-a39d-38f2a9790b85">2.2.6 WBEM_GENERIC_FLAG_TYPE Enumeration</a>
664 	 */
665 	private static final int WBEM_FLAG_RETURN_WBEM_COMPLETE = 0;
666 
667 	private static final String WQL = "WQL";
668 
669 	/** //hostname/namespace or just namespace for localhost */
670 	private final String networkResource;
671 
672 	/** Hostname we're connected to */
673 	private final String hostname;
674 
675 	/** Username (may be null) */
676 	private final String username;
677 
678 	/** Password (may be null) */
679 	private final char[] password;
680 
681 	/** WbemService instance (once it's connected) */
682 	private final IWbemServices wbemServices;
683 
684 	/** WbemLocator instance */
685 	private final IWbemLocator wbemLocator;
686 
687 	/** WbemContext to be used for this connection */
688 	private final IWbemContext context;
689 
690 	/** COAUTHIDENTITY structure holding domain, username and password */
691 	private final CoAuthIdentity authIdent;
692 
693 	/** Whether the instance has been closed */
694 	private boolean isClosed = false;
695 
696 	/** ReadWriteLock */
697 	private AutoCloseableReadWriteLock lock;
698 
699 	/**
700 	 * The WmiWbemServices constructor.
701 	 *
702 	 * @param networkResource //hostname/namespace or just namespace for localhost.
703 	 * @param username Username (may be null).
704 	 * @param password Password (may be null).
705 	 * @param wbemServices WbemService instance (once it's connected).
706 	 * @param wbemLocator WbemLocator instance.
707 	 * @param context WbemContext to be used for this connection.
708 	 * @param authIdent COAUTHIDENTITY structure holding domain, username and password.
709 	 */
710 	private WmiWbemServices(
711 		final String networkResource,
712 		final String username,
713 		final char[] password,
714 		final IWbemServices wbemServices,
715 		final IWbemLocator wbemLocator,
716 		final IWbemContext context,
717 		final CoAuthIdentity authIdent
718 	) {
719 		this.networkResource = networkResource;
720 		this.username = username;
721 		this.password = password;
722 		this.wbemServices = wbemServices;
723 		this.wbemLocator = wbemLocator;
724 		this.context = context;
725 		this.authIdent = authIdent;
726 		this.hostname =
727 			(networkResource != null && networkResource.startsWith("\\\\")) ? networkResource.split("\\\\")[2] : null;
728 		this.lock = new AutoCloseableReadWriteLock();
729 	}
730 
731 	/**
732 	 * Get a WmiWbemServices instance for the specified networkResource.
733 	 * @param networkResource \\hostname\namespace or just namespace for localhost (mandatory)
734 	 * @param username The username name (may be null).
735 	 * @param password The password (may be null).
736 	 * @return WmiWbemServices instance
737 	 *
738 	 * @throws WmiComException For any problem encountered with JNA
739 	 */
740 	public static WmiWbemServices getInstance(final String networkResource, final String username, final char[] password)
741 		throws WmiComException {
742 		Utils.checkNonNull(networkResource, "networkResource");
743 
744 		// Make sure username and password are null if networkResource is local
745 		if (WmiHelper.isLocalNetworkResource(networkResource) && (username != null || password != null)) {
746 			throw new IllegalArgumentException("A local resource must be accessed without specific credentials");
747 		}
748 
749 		IWbemLocator jnaWbemLocator = null;
750 		IWbemContext jnaWbemContext = null;
751 		IWbemServices jnaWbemServices = null;
752 
753 		try {
754 			// Initialize COM
755 			// Step 1 and 2 from: "https://docs.microsoft.com/en-us/windows/win32/wmisdk/example--getting-wmi-data-from-a-remote-computer"
756 			WmiComHelper.initializeComLibrary();
757 
758 			// Get a WbemLocator object (if we don't already have one)
759 			// Step 3 from: "https://docs.microsoft.com/en-us/windows/win32/wmisdk/example--getting-wmi-data-from-a-remote-computer"
760 			jnaWbemLocator = IWbemLocator.create();
761 			if (jnaWbemLocator == null) {
762 				throw new COMException("Failed to create WbemLocator object.");
763 			}
764 
765 			// WbemContext
766 			jnaWbemContext = createWbemContextFor64BitWbemProvider();
767 
768 			// Get the WbemServices
769 			jnaWbemServices =
770 				jnaWbemLocator.ConnectServer(
771 					networkResource,
772 					username,
773 					password == null ? null : String.valueOf(password),
774 					null,
775 					0,
776 					null,
777 					jnaWbemContext
778 				);
779 
780 			final CoAuthIdentity authIdent = username != null && !username.isEmpty()
781 				? new CoAuthIdentity(username, password)
782 				: null;
783 
784 			// The WbemServices instances is actually a proxy
785 			// Set the proxy blanket (cloaking)
786 			WmiWbemServices.setProxySecurity(jnaWbemServices.getPointer(), authIdent);
787 
788 			return new WmiWbemServices(
789 				networkResource,
790 				username,
791 				password,
792 				jnaWbemServices,
793 				jnaWbemLocator,
794 				jnaWbemContext,
795 				authIdent
796 			);
797 		} catch (final COMException e) {
798 			// Release what can be released
799 			if (jnaWbemServices != null) {
800 				jnaWbemServices.Release();
801 			}
802 
803 			if (jnaWbemLocator != null) {
804 				jnaWbemLocator.Release();
805 			}
806 
807 			if (jnaWbemContext != null) {
808 				jnaWbemContext.Release();
809 			}
810 
811 			throw new WmiComException(e, e.getMessage());
812 		}
813 	}
814 
815 	/**
816 	 * Release the WBEM services, disconnect and remove from the cache
817 	 */
818 	@Override
819 	public synchronized void close() {
820 		try (AutoCloseableReadWriteLock.AutoCloseableWriteLock writeLock = lock.write()) {
821 			isClosed = true;
822 
823 			if (context != null) {
824 				context.Release();
825 			}
826 
827 			if (wbemServices != null) {
828 				wbemServices.Release();
829 			}
830 
831 			if (wbemLocator != null) {
832 				wbemLocator.Release();
833 			}
834 		}
835 	}
836 
837 	/**
838 	 * Throws an IllegalStateException if the instance has been closed.
839 	 */
840 	private void checkState() {
841 		if (isClosed) {
842 			throw new IllegalStateException("This instance was closed");
843 		}
844 	}
845 
846 	/**
847 	 * <p>Execute a WQL query and process its result.</p>
848 	 * <p>Use the IWbemServices pointer to make requests of WMI.</p>
849 	 *
850 	 * <p>Step 6 from: <a href="https://docs.microsoft.com/en-us/windows/win32/wmisdk/example--getting-wmi-data-from-a-remote-computer">Example: Getting WMI Data from a Remote Computer</a></p>
851 	 *
852 	 * @param wql the WQL query (required)
853 	 * @param timeout Timeout in milliseconds (throws an IllegalArgumentException if negative or zero)
854 	 * @return a list of result rows. A result row is a Map(LinkedHashMap to preserve the query order) of properties/values.
855 	 * @throws TimeoutException to notify userName of timeout.
856 	 * @throws WqlQuerySyntaxException if WQL query syntax is invalid
857 	 * @throws WmiComException on any COM problem
858 	 */
859 	@Override
860 	public List<Map<String, Object>> executeWql(final String wql, final long timeout)
861 		throws TimeoutException, WqlQuerySyntaxException, WmiComException {
862 		// Parse the WQL
863 		WqlQuery wqlQuery = WqlQuery.newInstance(wql);
864 
865 		return executeWql(wqlQuery, timeout);
866 	}
867 
868 	/**
869 	 * <p>Execute a WQL query and process its result.</p>
870 	 * <p>Use the IWbemServices pointer to make requests of WMI.</p>
871 	 *
872 	 * <p>Step 6 from: <a href="https://docs.microsoft.com/en-us/windows/win32/wmisdk/example--getting-wmi-data-from-a-remote-computer">Example: Getting WMI Data from a Remote Computer</a></p>
873 	 *
874 	 * @param wqlQuery the WQL query (as a {@link WqlQuery} instance)
875 	 * @param timeout Timeout in milliseconds (throws an IllegalArgumentException if negative or zero)
876 	 * @return a list of result rows. A result row is a Map(LinkedHashMap to preserve the query order) of properties/values.
877 	 * @throws TimeoutException to notify userName of timeout.
878 	 * @throws WqlQuerySyntaxException if WQL query syntax is invalid
879 	 * @throws WmiComException on any COM problem
880 	 */
881 	public List<Map<String, Object>> executeWql(final WqlQuery wqlQuery, final long timeout)
882 		throws TimeoutException, WmiComException, WqlQuerySyntaxException {
883 		try (AutoCloseableReadWriteLock.AutoCloseableReadLock readLock = lock.read()) {
884 			checkState();
885 
886 			// Sanity check
887 			Utils.checkNonNullField(wbemServices, "wbemServices");
888 			Utils.checkNonNullField(wqlQuery, "wqlQuery");
889 			Utils.checkArgumentNotZeroOrNegative(timeout, "timeout");
890 
891 			// Get and parse the result
892 			IEnumWbemClassObject wbemClassObjectQueryResult = null;
893 			try {
894 				// Execute the query
895 				wbemClassObjectQueryResult =
896 					wbemServices.ExecQuery(
897 						WQL,
898 						wqlQuery.getCleanWql(),
899 						Wbemcli.WBEM_FLAG_FORWARD_ONLY | Wbemcli.WBEM_FLAG_RETURN_IMMEDIATELY,
900 						null
901 					);
902 
903 				return processWqlResult(wbemClassObjectQueryResult, authIdent, timeout, wqlQuery.getSubPropertiesMap());
904 			} catch (final COMException e) {
905 				// And forward this error as a regular exception
906 				throw new WmiComException(e, e.getClass().getSimpleName() + ": " + e.getMessage());
907 			} finally {
908 				if (wbemClassObjectQueryResult != null) {
909 					wbemClassObjectQueryResult.Release();
910 				}
911 			}
912 		}
913 	}
914 
915 	@Override
916 	public WindowsRemoteCommandResult executeCommand(
917 		final String command,
918 		final String workingDirectory,
919 		final Charset charset,
920 		final long timeout
921 	) throws WmiComException, TimeoutException {
922 		RemoteProcess.executeCommand(command, hostname, username, password, workingDirectory, timeout);
923 		return null;
924 	}
925 
926 	/**
927 	 * Sets the security and authentication blanket on the specified proxy pointer.
928 	 * <p>
929 	 * Step 5 from: <a href="https://docs.microsoft.com/en-us/windows/win32/wmisdk/example--getting-wmi-data-from-a-remote-computer">Example: Getting WMI Data from a Remote Computer</a>
930 	 * @param pProxy Pointer to the proxy object (WMI service, or enumerator)
931 	 * @param authIdent COAUTHIDENTITY structure holding domain, username and password.
932 	 * @throws WmiComException when security blanket cannot be configured
933 	 */
934 	static void setProxySecurity(final Pointer pProxy, final CoAuthIdentity authIdent) throws WmiComException {
935 		// Set proxy security so the WMI service can impersonate the client
936 		//
937 		final HRESULT hResult = Ole32Enhanced.INSTANCE.CoSetProxyBlanket(
938 			pProxy,
939 			Ole32Enhanced.RPC_C_AUTHN_DEFAULT,
940 			Ole32Enhanced.RPC_C_AUTHZ_DEFAULT,
941 			null,
942 			Ole32.RPC_C_AUTHN_LEVEL_CALL,
943 			Ole32.RPC_C_IMP_LEVEL_IMPERSONATE,
944 			authIdent,
945 			Ole32.EOAC_NONE
946 		);
947 		checkHResult(hResult, "Could not set proxy blanket");
948 	}
949 
950 	/**
951 	 * Create a context to force the 64 bits WBEM provider;
952 	 * We need to do that because the PATROL Agent will run in 32 bits mode
953 	 * and will thus access only the 32 bits version of the WBEM providers.
954 	 * The problem is that some WBEM providers are only available in 64 bits
955 	 * (notably some performance counters classes).
956 	 * <p>
957 	 * @see <a href="https://docs.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-iwbemcontext-setvalue">IWbemContext::SetValue method (wbemcli.h)</a>
958 	 * @return a WBEM context
959 	 */
960 	static IWbemContext createWbemContextFor64BitWbemProvider() {
961 		// Initialize COM (required)
962 		try {
963 			WmiComHelper.initializeComLibrary();
964 		} catch (final WmiComException e) {
965 			return null;
966 		}
967 
968 		// Create a WBEM Context instance
969 		final PointerByReference contextPointer = new PointerByReference();
970 		final HRESULT hCoCreateInstanceResult = Ole32.INSTANCE.CoCreateInstance(
971 			CLSID_WBEM_CONTEXT,
972 			null,
973 			WTypes.CLSCTX_INPROC_SERVER,
974 			IID_WBEM_CONTEXT,
975 			contextPointer
976 		);
977 		if (COMUtils.FAILED(hCoCreateInstanceResult)) {
978 			return null;
979 		}
980 
981 		// Set __ProviderArchitecture to 64
982 		final VARIANT value64 = new VARIANT(64);
983 		final ByReference byReference64 = new ByReference(value64);
984 		try {
985 			final HRESULT hResult = (HRESULT) WmiComHelper.comInvokerInvokeNativeObject(
986 				contextPointer.getValue(),
987 				SET_VALUE_FUNCTION_VTABLE_ID_IN_WBEM_CONTEXT_INTERFACE,
988 				new Object[] {
989 					contextPointer.getValue(),
990 					new WString(WBEMCONTEXT_NAME_FOR_PROVIDER_ARCHITECTURE),
991 					0,
992 					byReference64
993 				},
994 				HRESULT.class
995 			);
996 			return COMUtils.FAILED(hResult) ? null : new IWbemContext(contextPointer.getValue()); // Return the WBEM Context object
997 		} finally {
998 			OleAuto.INSTANCE.VariantClear(byReference64);
999 			OleAuto.INSTANCE.VariantClear(value64);
1000 		}
1001 	}
1002 
1003 	/**
1004 	 * <p>Get the data from the WQL query.</p>
1005 	 *
1006 	 * <p>Step 7 from: <a href="https://docs.microsoft.com/en-us/windows/win32/wmisdk/example--getting-wmi-data-from-a-remote-computer">Example: Getting WMI Data from a Remote Computer</a></p>
1007 	 *
1008 	 * @param wbemClassObjectQueryResult
1009 	 * @param authIdent COAUTHIDENTITY structure holding domain, username and password.
1010 	 * @param timeout Timeout in milliseconds
1011 	 * @param properties The properties to get from the request
1012 	 * @return a list of result rows. A result row is a Map(LinkedHashMap to preserve the query order) of properties/values.
1013 	 * @throws TimeoutException To notify userName of timeout.
1014 	 * @throws WmiComException on any COM problem
1015 	 * @throws WqlQuerySyntaxException on WQL syntax errors (as reported by WMI itself)
1016 	 */
1017 	private List<Map<String, Object>> processWqlResult(
1018 		final IEnumWbemClassObject wbemClassObjectQueryResult,
1019 		final CoAuthIdentity authIdent,
1020 		final long timeout,
1021 		final Map<String, Set<String>> properties
1022 	) throws TimeoutException, WmiComException, WqlQuerySyntaxException {
1023 		final Pointer[] pointersOnWbemClassObject = new Pointer[1];
1024 		final List<Map<String, Object>> resultRows = new ArrayList<>();
1025 		String[] names = null;
1026 		Map<String, Set<String>> normalizedProperties = null;
1027 
1028 		if (wbemClassObjectQueryResult.getPointer() != Pointer.NULL) {
1029 			setProxySecurity(wbemClassObjectQueryResult.getPointer(), authIdent);
1030 		}
1031 
1032 		while (wbemClassObjectQueryResult.getPointer() != Pointer.NULL) {
1033 			// Get the next record
1034 			final HRESULT hResult = wbemClassObjectQueryResult.Next(
1035 				(int) timeout,
1036 				pointersOnWbemClassObject.length,
1037 				pointersOnWbemClassObject,
1038 				new IntByReference(0)
1039 			);
1040 
1041 			// Any problem?
1042 			if (
1043 				hResult == null ||
1044 				hResult.intValue() == Wbemcli.WBEM_S_FALSE ||
1045 				hResult.intValue() == Wbemcli.WBEM_S_NO_MORE_DATA
1046 			) {
1047 				return resultRows;
1048 			}
1049 			if (hResult.intValue() == Wbemcli.WBEM_S_TIMEDOUT) {
1050 				throw new TimeoutException("No results after " + timeout + " ms.");
1051 			}
1052 			if (Integer.toUnsignedLong(hResult.intValue()) == 2147749911L) {
1053 				throw new WqlQuerySyntaxException("The query was not syntactically valid.");
1054 			}
1055 			checkHResult(hResult, "Failed to enumerate results");
1056 
1057 			// Get the actual WbemClassObject
1058 			final IWbemClassObject wbemClassObject = new IWbemClassObject(pointersOnWbemClassObject[0]);
1059 
1060 			try {
1061 				// Get the list of properties in the first record
1062 				// Note: this is done only the first time in this loop
1063 				if (names == null) {
1064 					try {
1065 						names = wbemClassObject.GetNames(null, 0, null);
1066 					} catch (final Throwable e) {
1067 						names = wbemClassObject.GetNames(null, 0, null);
1068 					}
1069 				}
1070 
1071 				if (normalizedProperties == null) {
1072 					normalizedProperties = normalizeProperties(names, properties);
1073 				}
1074 
1075 				// Add to the result
1076 				final Map<String, Object> values = getPropertiesValues(normalizedProperties, wbemClassObject);
1077 				resultRows.add(values);
1078 			} finally {
1079 				// Free memory for this WBEM object instance
1080 				wbemClassObject.Release();
1081 			}
1082 		}
1083 
1084 		return resultRows;
1085 	}
1086 
1087 	/**
1088 	 * Get all the values from the properties.
1089 	 *
1090 	 * @param properties
1091 	 * @param wbemClassObject wbemClassObject
1092 	 * @return
1093 	 */
1094 	private static HashMap<String, Object> getPropertiesValues(
1095 		final Map<String, Set<String>> properties,
1096 		final IWbemClassObject wbemClassObject
1097 	) {
1098 		return properties
1099 			.entrySet()
1100 			.stream()
1101 			.map(entry -> WmiCimTypeHandler.getPropertyValue(wbemClassObject, entry))
1102 			.flatMap(map -> map.entrySet().stream())
1103 			.collect(HashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue()), HashMap::putAll);
1104 	}
1105 
1106 	/**
1107 	 * Normalize the properties in initializing them if empty or null and replace their names with the one in the class.
1108 	 *
1109 	 * @param names
1110 	 * @param properties
1111 	 * @return
1112 	 */
1113 	private static Map<String, Set<String>> normalizeProperties(
1114 		final String[] names,
1115 		final Map<String, Set<String>> properties
1116 	) {
1117 		final Map<String, String> propertiesNames = Stream
1118 			.of(names)
1119 			.collect(Collectors.toMap(String::toLowerCase, Function.identity()));
1120 
1121 		return properties == null || properties.isEmpty()
1122 			? propertiesNames.values().stream().collect(Collectors.toMap(Function.identity(), p -> Collections.emptySet()))
1123 			: properties // Put the real property name from the class
1124 				.entrySet()
1125 				.stream()
1126 				.collect(
1127 					HashMap::new,
1128 					(map, entry) -> map.put(propertiesNames.get(entry.getKey().toLowerCase()), entry.getValue()),
1129 					HashMap::putAll
1130 				);
1131 	}
1132 
1133 	/**
1134 	 * <p>Invoke the IWbemServices::GetObject method.</p>
1135 	 * <p>The IWbemServices::GetObject method retrieves a class or instance.</p>
1136 	 * @see <a href="https://docs.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-iwbemservices-getobject">IWbemServices::GetObject method (wbemcli.h)</a>
1137 	 *
1138 	 *  Pointer on IWbemServices instance.
1139 	 *
1140 	 * @param objectPath Path of the object to retrieve. (mandatory)
1141 	 * @return A pointer on IWbemClassObject.
1142 	 *
1143 	 * @throws WmiComException For any problem encountered with JNA.
1144 	 */
1145 	public Pointer getObject(final String objectPath) throws WmiComException {
1146 		try (AutoCloseableReadWriteLock.AutoCloseableReadLock readLock = lock.read()) {
1147 			checkState();
1148 
1149 			Utils.checkNonNull(objectPath, "objectPath");
1150 
1151 			final Pointer pWbemServices = wbemServices.getPointer();
1152 
1153 			final BSTR strObjectPath = OleAuto.INSTANCE.SysAllocString(objectPath);
1154 			final int lFlags = WBEM_FLAG_RETURN_WBEM_COMPLETE;
1155 			final Pointer pCtx = null;
1156 			final PointerByReference ppObject = new PointerByReference();
1157 			final PointerByReference ppCallResult = null;
1158 
1159 			try {
1160 				final HRESULT hResult = (HRESULT) WmiComHelper.comInvokerInvokeNativeObject(
1161 					pWbemServices,
1162 					WBEM_SERVICES_GET_OBJECT_VTABLE_ID,
1163 					new Object[] { pWbemServices, strObjectPath, lFlags, pCtx, ppObject, ppCallResult },
1164 					HRESULT.class
1165 				);
1166 				WmiWbemServices.checkHResult(hResult, "Fail to invoke WbemServices::GetObject method");
1167 
1168 				return ppObject.getValue();
1169 			} finally {
1170 				OleAuto.INSTANCE.SysFreeString(strObjectPath);
1171 			}
1172 		}
1173 	}
1174 
1175 	/**
1176 	 * Executes the specified method of the specified class on the specified object.
1177 	 * Method inputs are specified as a Map&lt;String, Object&gt; mapping input names with
1178 	 * their values.
1179 	 * @param objectPath WBEM path to the object on which the method is to be executed
1180 	 * @param className Name of the class where the method is defined
1181 	 * @param methodName Name of the method to invoke
1182 	 * @param inputMap Map of input parameters for the method
1183 	 * @return a Map&lt;String, Object&gt; with the output parameters of the method
1184 	 * @throws WmiComException if anything goes wrong
1185 	 */
1186 	public Map<String, Object> executeMethod(
1187 		final String objectPath,
1188 		final String className,
1189 		final String methodName,
1190 		final Map<String, Object> inputMap
1191 	) throws WmiComException {
1192 		try (AutoCloseableReadWriteLock.AutoCloseableReadLock readLock = lock.read()) {
1193 			checkState();
1194 
1195 			// Get the class definition
1196 			final IWbemClassObject classDefinition = new IWbemClassObject(getObject(className));
1197 
1198 			// Get the method definition
1199 			final IWbemClassObject methodDefinition;
1200 			try {
1201 				methodDefinition = new IWbemClassObject(getMethod(classDefinition.getPointer(), methodName));
1202 			} finally {
1203 				classDefinition.Release();
1204 			}
1205 
1206 			// Create an "instance" of the method definition (to put inputs in there)
1207 			final IWbemClassObject methodInputs;
1208 			try {
1209 				methodInputs = new IWbemClassObject(spawnInstance(methodDefinition.getPointer()));
1210 			} finally {
1211 				methodDefinition.Release();
1212 			}
1213 
1214 			// Create a VARIANT for each entry in the input map
1215 			final Map<String, VARIANT> variantInputMap = new HashMap<>();
1216 			inputMap.forEach((name, value) -> {
1217 				VARIANT variant;
1218 				if (value == null) {
1219 					variant = new VARIANT();
1220 				} else if (value instanceof String) {
1221 					variant = new VARIANT((String) value);
1222 				} else if (value instanceof Integer) {
1223 					variant = new VARIANT((int) value);
1224 				} else if (value instanceof Pointer) {
1225 					variant = new VARIANT((Pointer) value);
1226 				} else {
1227 					throw new IllegalArgumentException("Unsupported object type for " + name);
1228 				}
1229 				variantInputMap.put(name, variant);
1230 			});
1231 
1232 			// Call the method for real now
1233 			final IWbemClassObject methodOutputs;
1234 			try {
1235 				for (final Map.Entry<String, VARIANT> inputEntry : variantInputMap.entrySet()) {
1236 					objectPut(methodInputs.getPointer(), inputEntry.getKey(), inputEntry.getValue());
1237 				}
1238 
1239 				methodOutputs = new IWbemClassObject(executeMethod(objectPath, methodName, methodInputs.getPointer()));
1240 			} finally {
1241 				variantInputMap.forEach((name, value) -> OleAuto.INSTANCE.VariantClear(value));
1242 				methodInputs.Release();
1243 			}
1244 
1245 			// Extract the values from the method output and build a HashMap
1246 			try {
1247 				String[] properties;
1248 				try {
1249 					properties = methodOutputs.GetNames(null, 0, null);
1250 				} catch (final Throwable e) {
1251 					properties = methodOutputs.GetNames(null, 0, null);
1252 				}
1253 
1254 				final Map<String, Set<String>> normalizedProperties = normalizeProperties(properties, null);
1255 
1256 				return getPropertiesValues(normalizedProperties, methodOutputs);
1257 			} finally {
1258 				methodOutputs.Release();
1259 			}
1260 		}
1261 	}
1262 
1263 	/**
1264 	 * <p>Invoke the IWbemServices::ExecMethod method.</p>
1265 	 * <p>The IWbemServices::ExecMethod method executes a method exported by a CIM object.</p>
1266 	 *
1267 	 * @see <a href="https://docs.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-iwbemservices-execmethod">IWbemServices::ExecMethod  method (wbemcli.h)</a>
1268 	 *
1269 	 * @param objectPath The object path of the object for which the method is executed. (mandatory)
1270 	 * @param methodName Name of the method for the object. (mandatory)
1271 	 * @param pInParams May be NULL if no in-parameters are required to execute the method.
1272 	 * Otherwise, this points to an IWbemClassObject that contains the properties acting as
1273 	 * inbound parameters for the method execution.
1274 	 * @return A pointer on Execution method output.
1275 	 *
1276 	 * @throws WmiComException For any problem encountered with JNA.
1277 	 */
1278 	Pointer executeMethod(final String objectPath, final String methodName, final Pointer pInParams)
1279 		throws WmiComException {
1280 		Utils.checkNonNull(objectPath, "objectPath");
1281 		Utils.checkNonNull(methodName, "methodName");
1282 
1283 		final Pointer pWbemServices = wbemServices.getPointer();
1284 
1285 		final BSTR strObjectPath = OleAuto.INSTANCE.SysAllocString(objectPath);
1286 		final BSTR strMethodName = OleAuto.INSTANCE.SysAllocString(methodName);
1287 		final int lFlags = 0;
1288 		final Pointer pCtx = null;
1289 		final PointerByReference ppOutParams = new PointerByReference();
1290 		final PointerByReference ppCallResult = null;
1291 
1292 		try {
1293 			final HRESULT hResult = (HRESULT) WmiComHelper.comInvokerInvokeNativeObject(
1294 				pWbemServices,
1295 				WBEM_SERVICES_EXEC_METHOD_VTABLE_ID,
1296 				new Object[] {
1297 					pWbemServices,
1298 					strObjectPath,
1299 					strMethodName,
1300 					lFlags,
1301 					pCtx,
1302 					pInParams,
1303 					ppOutParams,
1304 					ppCallResult
1305 				},
1306 				HRESULT.class
1307 			);
1308 			WmiWbemServices.checkHResult(hResult, "Failed to invoke WbemServices::ExecMethod method");
1309 			return ppOutParams.getValue();
1310 		} finally {
1311 			OleAuto.INSTANCE.SysFreeString(strObjectPath);
1312 			OleAuto.INSTANCE.SysFreeString(strMethodName);
1313 		}
1314 	}
1315 
1316 	/**
1317 	 * <p>Invoke the IWbemClassObject::Put method.</p>
1318 	 * <p>The IWbemClassObject::Put method sets a named property to a new value.</p>
1319 	 * @see <a href="https://docs.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-iwbemclassobject-put">IWbemClassObject::Put  method (wbemcli.h)</a>
1320 	 *
1321 	 * @param pWbemClassObject A pointer on IWbemClassObject. (mandatory)
1322 	 * @param propertyName A parameter that must point to a valid property name. (mandatory)
1323 	 * @param pVal A parameter that must point to a valid VARIANT, which becomes the new property value.
1324 	 * If pVal is NULL or points to a VARIANT of type VT_NULL, the property is set to NULL, that is, no value.
1325 	 *
1326 	 * @throws WmiComException For any problem encountered with JNA.
1327 	 */
1328 	public void objectPut(final Pointer pWbemClassObject, final String propertyName, final Variant.VARIANT pVal)
1329 		throws WmiComException {
1330 		try (AutoCloseableReadWriteLock.AutoCloseableReadLock readLock = lock.read()) {
1331 			checkState();
1332 
1333 			Utils.checkNonNull(pWbemClassObject, "pWbemClassObject");
1334 			Utils.checkNonNull(propertyName, "propertyName");
1335 
1336 			final WString wszName = new WString(propertyName);
1337 
1338 			// According to IWbemClassObject::Put docs, if pVal isn't VT_NULL,
1339 			// setting Type to 0 directs WMI to infer the CIM type from the VARIANT.
1340 			// IWbemClassObject::Put docs: https://docs.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-iwbemclassobject-put
1341 			final HRESULT hResult = (HRESULT) WmiComHelper.comInvokerInvokeNativeObject(
1342 				pWbemClassObject,
1343 				WBEM_CLASS_OBJECT_PUT_VTABLE_ID,
1344 				new Object[] {
1345 					pWbemClassObject,
1346 					wszName,
1347 					0, // lFlags -- Reserved, must be zero
1348 					pVal,
1349 					0
1350 				},
1351 				HRESULT.class
1352 			);
1353 			WmiWbemServices.checkHResult(hResult, "Fail to invoke IWbemClassObject::Put method");
1354 		}
1355 	}
1356 
1357 	/**
1358 	 * <p>Invoke the IWbemClassObject::SpawnInstance method.</p>
1359 	 * <p>Use the IWbemClassObject::SpawnInstance method to create a new instance of a class.</p>
1360 	 * @see <a href="https://docs.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-iwbemclassobject-spawninstance">IWbemClassObject::SpawnInstance  method (wbemcli.h)</a>
1361 	 *
1362 	 * @param pWbemClassObject A pointer on IWbemClassObject. (mandatory)
1363 	 * @return A pointer on instantiated WBEM Class object.
1364 	 *
1365 	 * @throws WmiComException For any problem encountered with JNA.
1366 	 */
1367 	public Pointer spawnInstance(final Pointer pWbemClassObject) throws WmiComException {
1368 		try (AutoCloseableReadWriteLock.AutoCloseableReadLock readLock = lock.read()) {
1369 			checkState();
1370 
1371 			Utils.checkNonNull(pWbemClassObject, "pWbemClassObject");
1372 
1373 			final int lFlags = 0;
1374 			final PointerByReference ppNewInstance = new PointerByReference();
1375 
1376 			final HRESULT hResult = (HRESULT) WmiComHelper.comInvokerInvokeNativeObject(
1377 				pWbemClassObject,
1378 				WBEM_CLASS_OBJECT_SPAWN_INSTANCE_VTABLE_ID,
1379 				new Object[] { pWbemClassObject, lFlags, ppNewInstance },
1380 				HRESULT.class
1381 			);
1382 			WmiWbemServices.checkHResult(hResult, "Fail to invoke IWbemClassObject::SpawnInstance method");
1383 
1384 			return ppNewInstance.getValue();
1385 		}
1386 	}
1387 
1388 	/**
1389 	 * <p>Invoke the IWbemClassObject::getMethod method.</p>
1390 	 * <p>The IWbemClassObject::GetMethod method returns information about the requested method.</p>
1391 	 * @see <a href="https://docs.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-iwbemclassobject-getmethod">IWbemClassObject::GetMethod   method (wbemcli.h)</a>
1392 
1393 	 * @param pWbemClassObject A pointer on IWbemClassObject. (mandatory)
1394 	 * @param methodName The method name. This cannot be NULL. (mandatory)
1395 	 * @return A pointer on getMethod method.
1396 	 *
1397 	 * @throws WmiComException For any problem encountered with JNA.
1398 	 */
1399 	Pointer getMethod(final Pointer pWbemClassObject, final String methodName) throws WmiComException {
1400 		Utils.checkNonNull(pWbemClassObject, "pWbemClassObject");
1401 		Utils.checkNonNull(methodName, "methodName");
1402 
1403 		final WString wszName = new WString(methodName);
1404 		final int lFlags = 0;
1405 		final PointerByReference ppInSignature = new PointerByReference();
1406 		final PointerByReference ppOutSignature = null;
1407 
1408 		final HRESULT hResult = (HRESULT) WmiComHelper.comInvokerInvokeNativeObject(
1409 			pWbemClassObject,
1410 			WBEM_CLASS_OBJECT_GET_METHOD_VTABLE_ID,
1411 			new Object[] { pWbemClassObject, wszName, lFlags, ppInSignature, ppOutSignature },
1412 			HRESULT.class
1413 		);
1414 		WmiWbemServices.checkHResult(hResult, "Fail to invoke IWbemClassObject::getMethod method");
1415 		return ppInSignature.getValue();
1416 	}
1417 
1418 	public String getNetworkResource() {
1419 		return networkResource;
1420 	}
1421 
1422 	@Override
1423 	public String getHostname() {
1424 		return hostname;
1425 	}
1426 
1427 	@Override
1428 	public String getUsername() {
1429 		return username;
1430 	}
1431 
1432 	@Override
1433 	public char[] getPassword() {
1434 		return password;
1435 	}
1436 
1437 	public IWbemServices getWbemServices() {
1438 		return wbemServices;
1439 	}
1440 
1441 	public IWbemLocator getWbemLocator() {
1442 		return wbemLocator;
1443 	}
1444 
1445 	public IWbemContext getContext() {
1446 		return context;
1447 	}
1448 
1449 	public CoAuthIdentity getAuthIdent() {
1450 		return authIdent;
1451 	}
1452 
1453 	public boolean isClosed() {
1454 		return isClosed;
1455 	}
1456 }