windows_win/
lib.rs

1#![cfg(windows)]
2//! Windows WinAPI
3//!
4//! Some windows hacking library with utilities to find windows and access them.
5//!
6
7#![warn(missing_docs)]
8#![cfg_attr(feature = "cargo-clippy", allow(clippy::not_unsafe_ptr_arg_deref))]
9#![cfg_attr(feature = "cargo-clippy", allow(clippy::style))]
10#![cfg_attr(feature = "cargo-clippy", allow(clippy::derivable_impls))]
11
12pub mod sys;
13
14use std::ffi;
15use core::{ptr, mem, convert};
16
17#[path="raw/mod.rs"]
18mod inner_raw;
19pub mod utils;
20pub mod ui;
21
22pub use utils::{ErrorCode, Result};
23
24pub mod raw {
25    //! Provides direct bindings to WinAPI functions of crate.
26    pub use super::inner_raw::process;
27    pub use super::inner_raw::window;
28    pub use super::inner_raw::message;
29    pub use super::inner_raw::file;
30    pub use super::inner_raw::memory;
31    pub use super::inner_raw::module;
32    pub use super::inner_raw::timer;
33}
34
35use sys::{
36    HANDLE,
37    HWND,
38    UINT,
39    WPARAM,
40    LPARAM,
41    LRESULT,
42    MSG,
43    c_uint,
44    c_ulong,
45    c_void,
46    c_uchar,
47    SW_SHOW,
48    SW_HIDE
49};
50
51///Windows process representation
52pub struct Process {
53    pid: u32,
54    inner: HANDLE,
55}
56
57impl Process {
58    ///Creates handle to a new process by opening it through pid.
59    ///
60    ///# Note:
61    ///See information about access rights:
62    ///https://msdn.microsoft.com/en-us/library/windows/desktop/ms684880%28v=vs.85%29.aspx
63    ///
64    ///# Parameters:
65    ///
66    ///* ```pid``` - Pid of the process.
67    ///* ```access_rights``` - Bit mask that specifies desired access rights.
68    ///
69    ///# Return:
70    ///
71    ///* ```Ok``` - Process struct.
72    ///* ```Err``` - Error reason.
73    pub fn open(pid: u32, access_rights: u32) -> utils::Result<Process> {
74        match raw::process::open(pid, access_rights) {
75            Ok(handle) => Ok(Process {
76                pid: pid,
77                inner: handle,
78            }),
79            Err(error) => Err(error),
80        }
81    }
82
83    ///Creates instance from existing handle
84    pub fn from_raw(handle: HANDLE) -> Self {
85        Process {
86            pid: raw::process::get_id(handle),
87            inner: handle
88        }
89    }
90
91    #[inline]
92    ///Retrieves underlying handle.
93    pub fn inner(&self) -> HANDLE {
94        self.inner
95    }
96
97    #[inline]
98    ///Retrieves underlying handle and consumes self.
99    ///
100    ///Basically you're responsible to close handle now.
101    pub fn into_inner(self) -> HANDLE {
102        let result = self.inner;
103        mem::forget(self);
104        result
105    }
106
107    #[inline]
108    ///Gets full path to process's exectuable.
109    ///
110    ///# Note
111    ///
112    /// The process MUST be opened with either PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION flag.
113    ///
114    ///# Return
115    ///
116    ///* ```Ok``` - Success.
117    ///* ```Err``` - Error reason.
118    pub fn exe_path(&self) -> Result<String> {
119        raw::process::get_exe_path(self.inner)
120    }
121
122    #[inline]
123    ///Retrieves handle to process's window
124    ///
125    ///# Note
126    ///
127    ///It can return ```None``` if process hasn't created window.
128    pub fn window(&self) -> Result<Option<HWND>> {
129        raw::window::get_by_pid(self.pid)
130    }
131
132    #[inline]
133    ///Reads memory from process.
134    ///
135    ///# Parameters:
136    ///
137    ///* ```base_addr``` - Address from where to start reading.
138    ///* ```storage``` - Storage to hold memory. Its `len` determines amount of bytes to read.
139    pub fn read_memory(&self, base_addr: usize, storage: &mut [u8]) -> Result<()> {
140        raw::process::read_memory(self.inner, base_addr, storage)
141    }
142
143    #[inline]
144    ///Writes into process memory.
145    ///
146    ///# Parameters:
147    ///
148    ///* ```base_addr``` - Address from where to start writing.
149    ///* ```data``` - Slice with write data.
150    ///
151    ///# Return:
152    ///
153    ///* ```Ok``` - Success.
154    ///* ```Err``` - Error reason.
155    pub fn write_memory(&self, base_addr: usize, data: &[u8]) -> Result<()> {
156        raw::process::write_memory(self.inner, base_addr, data)
157    }
158
159    ///Closes process
160    ///
161    ///# Note:
162    ///
163    ///There is no need to explicitly close the process.
164    ///
165    ///It shall be closed automatically when being dropped.
166    pub fn close(&mut self) {
167        if !self.inner.is_null() {
168            raw::process::close(self.inner).expect("Unable to close process");
169            self.inner = ptr::null_mut();
170        }
171    }
172
173    ///Forces termination of process and consumes itself.
174    ///
175    ///For details see [raw::process::terminate()](raw/process/fn.terminate.html).
176    pub fn terminate(self, exit_code: c_uint) -> Result<()> {
177        raw::process::terminate(self.inner, exit_code).map(|_| {
178            let _ = self.into_inner();
179        })
180    }
181}
182
183impl Drop for Process {
184    fn drop(&mut self) {
185        self.close()
186    }
187}
188
189///Wrapper over Windows messages.
190///
191///On drop it translates and dispatches message.
192///You can do it yourself though.
193pub struct Msg {
194    inner: MSG
195}
196
197impl Msg {
198    ///Creates new instance by taking raw `MSG`
199    pub fn new(message: MSG) -> Msg {
200        Msg {
201            inner: message
202        }
203    }
204
205    #[inline]
206    ///Message identifier.
207    pub fn id(&self) -> UINT {
208        self.inner.message
209    }
210
211    #[inline]
212    ///Pointer to inner message.
213    pub fn as_ptr(&self) -> *const MSG {
214        &self.inner as *const MSG
215    }
216
217    #[inline]
218    ///Mutable pointer to inner message.
219    pub fn as_mut_ptr(&mut self) -> *mut MSG {
220        &mut self.inner as *mut MSG
221    }
222
223    #[inline]
224    ///Retrieves raw Windows Message.
225    ///
226    ///Ownership is not passed so do not manually dispatch it.
227    pub fn inner(&self) -> MSG {
228        self.inner
229    }
230
231    #[inline]
232    ///Retrieves raw Windows Message and transfers ownership.
233    ///
234    ///After that user is responsible to dispatch message.
235    pub fn into_inner(self) -> MSG {
236        let result = self.inner;
237        mem::forget(self);
238        result
239    }
240
241    #[inline]
242    ///Drops and Dispatches underlying Windows Message.
243    ///You cannot use it after that.
244    pub fn dispatch(self) {
245        drop(self);
246    }
247}
248
249impl Drop for Msg {
250    fn drop(&mut self) {
251        raw::message::translate(self.as_mut_ptr());
252        raw::message::dispatch(self.as_mut_ptr());
253    }
254}
255
256///Iterator over Windows messages
257///
258///Under hood it uses [get()](raw/message/fn.get.html).
259///
260///Similarly to this function you can configure:
261///
262///* window - For which window to received messages.
263///* range - Range of message identifiers to receive.
264pub struct Messages {
265    window: Option<HWND>,
266    range: (Option<UINT>, Option<UINT>),
267    is_block: bool
268}
269
270impl Messages {
271    ///Initializes new iterator with default no filtering.
272    pub fn new() -> Messages {
273        Messages {
274            window: None,
275            range: (None, None),
276            is_block: true
277        }
278    }
279
280    ///Sets window for which to receive messages.
281    pub fn window(&mut self, window: Option<HWND>) -> &mut Messages {
282        self.window = window;
283        self
284    }
285
286    ///Sets low range of message identifiers.
287    pub fn low(&mut self, low: Option<UINT>) -> &mut Messages {
288        self.range.0 = low;
289        self
290    }
291
292    ///Sets high range of message identifiers.
293    pub fn high(&mut self, high: Option<UINT>) -> &mut Messages {
294        self.range.1 = high;
295        self
296    }
297
298    ///Sets blocking mode.
299    pub fn blocking(&mut self) -> &mut Messages {
300        self.is_block = true;
301        self
302    }
303
304    ///Sets non blocking mode.
305    ///
306    ///You can provide how to handle retrieved messages as in [peek()](raw/message/fn.peek.html).
307    ///It sets `PM_REMOVE` to remove message, but not that it is not always guaranteed.
308    ///See docs on `PeekMessage`
309    pub fn non_blocking(&mut self) -> &mut Messages {
310        self.is_block = false;
311        self
312    }
313}
314
315impl Iterator for Messages {
316    type Item = Result<Msg>;
317
318    ///Retrieves next message in queue.
319    ///
320    ///Blocking call.
321    fn next(&mut self) -> Option<Self::Item> {
322        if self.is_block {
323            Some(raw::message::get(self.window, self.range.0, self.range.1).map(|msg| Msg::new(msg)))
324        }
325        else {
326            match raw::message::peek(self.window, self.range.0, self.range.1, Some(0x0001)) {
327                Ok(Some(msg)) => Some(Ok(Msg::new(msg))),
328                Ok(None) => None,
329                Err(error) => Some(Err(error))
330            }
331        }
332    }
333}
334
335///Convenient wrapper over Window.
336///
337///Note that while you can use it with any window.
338///It makes no sense in taking ownership of not created by you windows.
339///
340///This struct destroys window on drop and it is bad idea to do it for not your own window.
341///If lucky, it fails but still not great idea.
342pub struct Window {
343    inner: HWND
344}
345
346impl Window {
347    #[inline]
348    ///Creates new instance by taking ownership over provided window.
349    pub fn from_hwnd(window: HWND) -> Self {
350        Window { inner: window }
351    }
352
353    #[inline]
354    ///Creates window from instance of window builder.
355    pub fn from_builder(builder: &mut raw::window::Builder) -> Result<Self> {
356        builder.create().map(|win| Window::from_hwnd(win))
357    }
358
359    #[inline]
360    ///Returns underlying window.
361    ///
362    ///Ownership is not passed.
363    pub fn inner(&self) -> HWND {
364        self.inner
365    }
366
367    #[inline]
368    ///Transfers ownership of underlying window.
369    pub fn into_inner(self) -> HWND {
370        let result = self.inner;
371        mem::forget(self);
372        result
373    }
374
375    #[inline]
376    ///Shows window.
377    ///
378    ///Returns true if previously it wasn't visible
379    pub fn show(&self) -> bool {
380        !raw::window::show(self.inner, SW_SHOW)
381    }
382
383    #[inline]
384    ///Hide window.
385    ///
386    ///Returns true if previously it was visible
387    pub fn hide(&self) -> bool {
388        raw::window::show(self.inner, SW_HIDE)
389    }
390
391    #[inline]
392    ///Returns whether window is visible.
393    pub fn is_visible(&self) -> bool {
394        raw::window::is_visible(self.inner)
395    }
396
397    #[inline]
398    ///Retrieves window's class.
399    pub fn class(&self) -> Result<String> {
400        raw::window::get_class(self.inner)
401    }
402
403    #[inline]
404    ///Retrieves window's title.
405    pub fn title(&self) -> Result<String> {
406        raw::window::get_text(self.inner)
407    }
408
409    #[inline]
410    ///Retrieves tuple of thread and process ids.
411    pub fn thread_pid(&self) -> (u32, u32) {
412        raw::window::get_thread_process_id(self.inner)
413    }
414
415    #[inline]
416    ///Sends message to underlying window.
417    ///
418    ///For more information refer to [send_message()](raw/window/fn.send_message.html)
419    pub fn send_message(&self, msg_type: UINT, w_param: WPARAM, l_param: LPARAM, timeout: Option<UINT>) -> Result<LRESULT> {
420        raw::window::send_message(self.inner, msg_type, w_param, l_param, timeout)
421    }
422
423    #[inline]
424    ///Sends `BM_CLICK` message to underlying window.
425    ///
426    ///For mores information refer to [send_push_button()](raw/window/fn.send_push_button.html)
427    pub fn send_push_button(&self, timeout: Option<UINT>) -> Result<LRESULT> {
428        raw::window::send_push_button(self.inner, timeout)
429    }
430
431    #[inline]
432    ///Sends `WM_SETTEXT` message to underlying window with new text.
433    ///
434    ///For more information refer to [send_set_text()](raw/window/fn.send_set_text.html)
435    pub fn send_set_text<T: AsRef<ffi::OsStr>>(&self, text: T) -> bool {
436        raw::window::send_set_text(self.inner, text)
437    }
438
439    #[inline]
440    ///Sends `WM_GETTEXT` message to underlying window and returns, if possible, corresponding text.
441    ///
442    ///For more information refer to [send_get_text()](raw/window/fn.send_get_text.html)
443    pub fn send_get_text(&self) -> Option<String> {
444        raw::window::send_get_text(self.inner)
445    }
446
447    #[inline]
448    ///Sends `WM_SYSCOMMAND` message to underlying window and returns, if possible, corresponding text.
449    ///
450    ///For more information refer to [send_sys_command()](raw/window/fn.send_sys_command.html)
451    pub fn send_sys_command(&self, cmd_type: WPARAM, l_param: LPARAM) -> bool {
452        raw::window::send_sys_command(self.inner, cmd_type, l_param)
453    }
454
455    #[inline]
456    ///Destroys underlying window and drops self.
457    pub fn destroy(self) {
458        drop(self);
459    }
460}
461
462impl convert::From<HWND> for Window {
463    fn from(window: HWND) -> Window {
464        Window { inner: window }
465    }
466}
467
468impl convert::Into<HWND> for Window {
469    fn into(self) -> HWND {
470        self.into_inner()
471    }
472}
473
474impl Drop for Window {
475    fn drop(&mut self) {
476        raw::window::destroy(self.inner);
477    }
478}
479
480enum TimerCallbackType {
481    None,
482    Raw(raw::timer::CallbackType, *mut c_void),
483}
484
485enum TimeoutType {
486    None,
487    Single(c_ulong),
488    Interval(c_ulong),
489    Both(c_ulong, c_ulong)
490}
491
492impl TimeoutType {
493    fn into_raw(self) -> (c_ulong, c_ulong) {
494        match self {
495            TimeoutType::None => (0, 0),
496            TimeoutType::Single(delay) => (delay, 0),
497            TimeoutType::Interval(interval) => (0, interval),
498            TimeoutType::Both(delay, interval) => (delay, interval),
499        }
500    }
501}
502
503unsafe extern "system" fn timer_rust_callback(param: *mut c_void, _: c_uchar) {
504    if !param.is_null() {
505        let cb: fn() -> () = mem::transmute(param);
506        cb();
507    }
508}
509
510///WinAPI timer builder
511///
512///The same timer can act as one-shot timer and/or interval timer.
513///
514///## Configuration
515///
516///When `single` method is called timer is configured as one-shot.
517///
518///When `interval` method is called timer is configured as interval.
519///
520///When both of the above  are called timer is configured as one-shot, after which it starts
521///to run in interval.
522///
523///By default timer starts as one-shot with timeout 0.
524pub struct TimerBuilder<'a> {
525    queue: Option<&'a raw::timer::TimerQueue>,
526    callback: TimerCallbackType,
527    timeout: TimeoutType,
528    flags: raw::timer::TimerFlags
529}
530
531impl<'a> TimerBuilder<'a> {
532    ///Creates new instance
533    pub fn new() -> Self {
534        Self {
535            queue: None,
536            callback: TimerCallbackType::None,
537            timeout: TimeoutType::None,
538            flags: raw::timer::DEFAULT_TIMER_FLAGS
539        }
540    }
541
542    ///Sets raw C function as callback
543    pub fn raw_callback(mut self, cb: raw::timer::CallbackType, param: Option<*mut c_void>) -> Self {
544        self.callback = TimerCallbackType::Raw(cb, param.unwrap_or(ptr::null_mut()));
545        self
546    }
547
548    ///Sets Rust function pointer as callback
549    pub fn rust_callback(mut self, cb: fn() -> ()) -> Self {
550        self.callback = TimerCallbackType::Raw(Some(timer_rust_callback), cb as _ );
551        self
552    }
553
554    ///Sets timer queue.
555    ///
556    ///If not set, default shall be used.
557    pub fn queue(mut self, queue: &'a raw::timer::TimerQueue) -> Self {
558        self.queue = Some(queue);
559        self
560    }
561
562    ///Makes timer to fire single time after delay in milliseconds.
563    pub fn single(mut self, delay: c_ulong) -> Self {
564        self.timeout = match self.timeout {
565            TimeoutType::Interval(interval) => TimeoutType::Both(delay, interval),
566            _ => TimeoutType::Single(delay)
567        };
568        self
569    }
570
571    ///Makes timer to fire with interval in milliseconds.
572    pub fn interval(mut self, interval: c_ulong) -> Self {
573        self.timeout = match self.timeout {
574            TimeoutType::Single(delay) => TimeoutType::Both(delay, interval),
575            _ => TimeoutType::Interval(interval)
576        };
577        self
578    }
579
580    ///Specifies timer flags.
581    ///
582    ///Default is `raw::timer::DEFAULT_TIMER_FLAGS`.
583    pub fn flags(mut self, flags: raw::timer::TimerFlags) -> Self {
584        self.flags = flags;
585        self
586    }
587
588    ///Creates timer.
589    pub fn build(self) -> Result<raw::timer::QueueTimer> {
590        static DEFAULT: raw::timer::TimerQueue = raw::timer::DEFAULT_TIMER_QUEUE;
591
592        let queue = self.queue.unwrap_or(&DEFAULT);
593        let (delay, period) = self.timeout.into_raw();
594        let (cb, param) = match self.callback {
595            TimerCallbackType::None => (None, ptr::null_mut()),
596            TimerCallbackType::Raw(cb, param) => (cb, param),
597        };
598
599        queue.timer(cb, param, delay, period, self.flags)
600    }
601}