1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
//! # WMI-rs
//!
//! [WMI] is a management API for Windows-based operating systems.
//! This crate provides both a high-level Rust API (focused on data retrieval, event queries and method execution),
//! as well as a mid-level API for easy access to native WMI methods.
//!
//! This crate also uses `serde` for transforming between native WMI class objects and plain Rust structs.
//!
//! # Quickstart
//!
//! Before using WMI, a connection must be created.
//!
//! ```rust
//! # fn main() -> wmi::WMIResult<()> {
//! use wmi::WMIConnection;
//! let wmi_con = WMIConnection::new()?;
//! # Ok(())
//! # }
//! ```
//!
//! There are multiple ways to get data from the OS using this crate.
//!
//! ## Operating on untyped `Variant`s
//!
//! WMI data model is based on COM's [`VARIANT`] Type, which is a struct capable of holding
//! many types of data.
//!
//! This crate provides the analogous [`wmi::Variant`] enum.
//!
//! Using this enum, we can execute a simple WMI query and inspect the results.
//!
//! ```edition2018
//! # fn main() -> wmi::WMIResult<()> {
//! use wmi::*;
//! let wmi_con = WMIConnection::new()?;
//! use std::collections::HashMap;
//! use wmi::Variant;
//! let results: Vec<HashMap<String, Variant>> = wmi_con.raw_query("SELECT * FROM Win32_OperatingSystem").unwrap();
//!
//! for os in results {
//! println!("{:#?}", os);
//! }
//! # Ok(())
//! # }
//! ```
//!
//! ## Using strongly typed data structures
//!
//! Using `serde`, it is possible to return a struct representing the the data.
//!
//! ```edition2018
//! # fn main() -> wmi::WMIResult<()> {
//! # use wmi::*;
//! # let wmi_con = WMIConnection::new()?;
//! use serde::Deserialize;
//! # #[cfg(feature = "chrono")]
//! use wmi::WMIDateTime;
//! # #[cfg(all(feature = "time", not(feature = "chrono")))]
//! # use wmi::WMIOffsetDateTime as WMIDateTime;
//!
//! #[derive(Deserialize, Debug)]
//! #[serde(rename = "Win32_OperatingSystem")]
//! #[serde(rename_all = "PascalCase")]
//! struct OperatingSystem {
//! caption: String,
//! debug: bool,
//! last_boot_up_time: WMIDateTime,
//! }
//!
//! let results: Vec<OperatingSystem> = wmi_con.query()?;
//!
//! for os in results {
//! println!("{:#?}", os);
//! }
//! # Ok(())
//! # }
//! ```
//!
//! Because the name of the struct given to `serde` matches the [WMI class] name, the SQL query
//! can be inferred.
//!
//! [WMI]: https://docs.microsoft.com/en-us/windows/desktop/wmisdk/about-wmi
//! [Creating a WMI Application Using C++]: https://docs.microsoft.com/en-us/windows/desktop/wmisdk/creating-a-wmi-application-using-c-
//! [`VARIANT`]: https://docs.microsoft.com/en-us/windows/desktop/api/oaidl/ns-oaidl-tagvariant
//! [WMI class]: https://docs.microsoft.com/en-us/windows/desktop/cimwin32prov/win32-operatingsystem
//!
//! # High-level API functions
//!
//! Queries and data retrieval - [`WMIConnection::query`], [`WMIConnection::filtered_query`], [`WMIConnection::get`], [`WMIConnection::get_by_path`] and [`WMIConnection::associators`].
//!
//! Event listening - [`WMIConnection::notification`] and [`WMIConnection::filtered_notification`].
//!
//! Method calling - [`WMIConnection::exec_class_method`] and [`WMIConnection::exec_instance_method`].
//!
//! Most of these have `async` versions as well.
//!
//! # Mid-level API functions
//!
//! Queries and data retrieval - [`WMIConnection::get_object`], [`WMIConnection::exec_query`] and [`WMIConnection::exec_query_async`].
//!
//! Event listening - [`WMIConnection::exec_notification_query`] and [`WMIConnection::exec_notification_query_async`].
//!
//! Method calling - [`WMIConnection::exec_method`] and [`IWbemClassWrapper`].
//!
//! These try to keep the names of the underlying WMI machinery.
//!
//! # Subscribing to event notifications
//!
//! Using this crate you can subscribe to events notifications generated upon changes in WMI data and services.
//!
//! When querying for events, it is important to remember there are two types of event notifications. \
//! The first one is notifications about changes to the standard WMI data models. They are called **intrinsic events**. \
//! Events like [`__InstanceCreationEvent`] or [`__NamespaceDeletionEvent`] are examples of such events.
//!
//! The second type is notifications about changes made by providers. They are called **extrinsic events**. \
//! Any WMI class deriving from the [`__ExtrinsicEvent`] class is an extrinsic event. \
//! An example of such events are [`Win32_ProcessStartTrace`] and [`Win32_VolumeChangeEvent`] classes.
//!
//! For more information about event queries, [see here](https://docs.microsoft.com/en-us/windows/win32/wmisdk/receiving-a-wmi-event#event-queries).\
//! You can use [WMI Code Creator] to see available events and create queries for them.
//!
//! The [`notification`] method returns an iterator that waits for any incoming events
//! resulting from the provided query. Loops reading from this iterator will not end until they are broken.
//!
//! An example of subscribing to an intrinsic event notification for every new [`Win32_Process`]
//! ```edition2018
//! # use wmi::*;
//! # #[cfg(not(feature = "test"))]
//! # fn main() {}
//! # #[cfg(feature = "test")]
//! # fn main() -> WMIResult<()>{
//! # use serde::Deserialize;
//! # use std::{collections::HashMap, time::Duration};
//! # let wmi_con = WMIConnection::new()?;
//! #[derive(Deserialize, Debug)]
//! #[serde(rename = "__InstanceCreationEvent")]
//! #[serde(rename_all = "PascalCase")]
//! struct NewProcessEvent {
//! target_instance: Process
//! }
//!
//! #[derive(Deserialize, Debug)]
//! #[serde(rename = "Win32_Process")]
//! #[serde(rename_all = "PascalCase")]
//! struct Process {
//! process_id: u32,
//! name: String,
//! executable_path: Option<String>,
//! }
//!
//! let mut filters = HashMap::<String, FilterValue>::new();
//!
//! filters.insert("TargetInstance".to_owned(), FilterValue::is_a::<Process>()?);
//!
//! let iterator = wmi_con.filtered_notification::<NewProcessEvent>(&filters, Some(Duration::from_secs(1)))?;
//! # tests::start_test_program();
//!
//! for result in iterator {
//! let process = result?.target_instance;
//! println!("New process!");
//! println!("PID: {}", process.process_id);
//! println!("Name: {}", process.name);
//! println!("Executable: {:?}", process.executable_path);
//! # break;
//! } // Loop will end only on error
//! # Ok(())
//! # }
//! ```
//!
//! An example of subscribing to an extrinsic event notification [`Win32_ProcessStartTrace`]
//! ```edition2018
//! # use wmi::*;
//! # #[cfg(not(feature = "test"))]
//! # fn main() {}
//! # #[cfg(feature = "test")]
//! # fn main() -> WMIResult<()> {
//! # tests::ignore_access_denied(run())
//! # }
//! # #[cfg(feature = "test")]
//! # fn run() -> WMIResult<()>{
//! # use serde::Deserialize;
//! # use std::{collections::HashMap, time::Duration};
//! # let wmi_con = WMIConnection::new()?;
//! #[derive(Deserialize, Debug)]
//! #[serde(rename = "Win32_ProcessStartTrace")]
//! #[serde(rename_all = "PascalCase")]
//! struct ProcessStartTrace {
//! process_id: u32,
//! process_name: String,
//! }
//!
//! let iterator = wmi_con.notification::<ProcessStartTrace>()?;
//! # tests::start_test_program();
//!
//! for result in iterator {
//! let trace = result?;
//! println!("Process started!");
//! println!("PID: {}", trace.process_id);
//! println!("Name: {}", trace.process_name);
//! # break;
//! } // Loop will end only on error
//! # Ok(())
//! # }
//! ```
//!
//! [`Win32_Process`]: https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-process
//! [`__InstanceCreationEvent`]: https://docs.microsoft.com/en-us/windows/win32/wmisdk/--instancecreationevent
//! [`__NamespaceDeletionEvent`]: https://docs.microsoft.com/en-us/windows/win32/wmisdk/--namespacedeletionevent
//! [`__ExtrinsicEvent`]: https://docs.microsoft.com/en-us/windows/win32/wmisdk/--extrinsicevent
//! [`Win32_ProcessStartTrace`]: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/krnlprov/win32-processstarttrace
//! [`Win32_VolumeChangeEvent`]: https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-volumechangeevent
//! [WMI Code Creator]: https://www.microsoft.com/en-us/download/details.aspx?id=8572
//! [`notification`]: connection/struct.WMIConnection.html#method.notification
//!
//! # Executing Methods
//!
//! The crate also offers support for executing WMI methods on classes and instances.
//!
//! See [`WMIConnection::exec_class_method`], [`WMIConnection::exec_instance_method`] and [`WMIConnection::exec_method`]
//! for detailed examples.
//!
//! # Custom Authentication Levels
//!
//! Some WMI namespaces require specific authentication levels when accessing
//! sensitive system information. Use [`WMIConnection::set_proxy_blanket`] to configure this,
//! which maps directly to the Windows [`CoSetProxyBlanket`] function.
//!
//! **Default Behavior**:
//! - Local connections: [`AuthLevel::Call`] (message authentication)
//! - Remote connections: [`AuthLevel::PktPrivacy`] (packet encryption)
//!
//! ```no_run
//! # use wmi::*;
//! use serde::Deserialize;
//!
//! # fn main() -> WMIResult<()> {
//! // Access BitLocker data, which requires packet-level encryption.
//! // Note: admin privileges are required for BitLocker queries.
//! let wmi_con = WMIConnection::with_namespace_path(
//! "ROOT\\CIMV2\\Security\\MicrosoftVolumeEncryption"
//! )?;
//! wmi_con.set_proxy_blanket(AuthLevel::PktPrivacy)?;
//!
//! #[derive(Deserialize, Debug)]
//! #[serde(rename = "Win32_EncryptableVolume")]
//! #[serde(rename_all = "PascalCase")]
//! struct EncryptableVolume {
//! device_id: String,
//! protection_status: Option<u32>, // 0=Unprotected, 1=Protected, 2=Unknown
//! }
//!
//! let volumes: Vec<EncryptableVolume> = wmi_con.query()?;
//! # Ok(())
//! # }
//! ```
//!
//! [`CoSetProxyBlanket`]: https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cosetproxyblanket
//!
//! # Internals
//!
//! [`WMIConnection`] is used to create and execute a WMI query, returning
//! [`IWbemClassWrapper`] which is a wrapper for a WMI object pointer.
//!
//! Then, `from_wbem_class_obj` is used to create a Rust struct with the equivalent data.
//!
//! Deserializing data from WMI and into Rust is done via `serde`.
//! More info can be found in `serde`'s documentation about [writing a data format].
//! The deserializer will either use the field names defined on the output struct,
//! or retrieve all field names from WMI if the output is a `HashMap`.
//!
//! [writing a data format]: https://serde.rs/data-format.html
//!
//! There are two main data structures (other than pointers to object) which convert native data to Rust data structures:
//! [`crate::Variant`] and [`SafeArrayAccessor`](safearray::SafeArrayAccessor).
//!
//! Most native objects has an equivalent wrapper struct which implements `Drop` for that data.
//!
//! # Async Query
//!
//! Async queries use WMI's native async support (but a runtime like `tokio`, `async-std` or `futures::executor::block_on` is still required).
//!
//! ```edition2018
//! # use futures::executor::block_on;
//! # block_on(exec_async_query()).unwrap();
//! # async fn exec_async_query() -> wmi::WMIResult<()> {
//! use wmi::*;
//! let wmi_con = WMIConnection::new()?;
//! use serde::Deserialize;
//!
//! #[derive(Deserialize, Debug)]
//! #[serde(rename = "Win32_OperatingSystem")]
//! #[serde(rename_all = "PascalCase")]
//! struct OperatingSystem {
//! caption: String,
//! debug: bool,
//! }
//!
//! let results: Vec<OperatingSystem> = wmi_con.async_query().await?;
//!
//! for os in results {
//! println!("{:#?}", os);
//! }
//! # Ok(())
//! # }
//! ```
//!
pub use ;
pub use WMIDateTime;
pub use WMIOffsetDateTime;
pub use ;
pub use WMIDuration;
pub use ;
pub use IWbemClassWrapper;
pub use ;
pub use Variant;
;