Skip to content

Commit b4caf0d

Browse files
committed
implement get_printers for windows
1 parent d427b46 commit b4caf0d

File tree

3 files changed

+83
-2
lines changed

3 files changed

+83
-2
lines changed

Cargo.lock

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

paperjet/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ doctest = false
1818
strum = { version = "0.27.2", features = ["derive"] }
1919
thiserror = "2.0.12"
2020

21+
[target.'cfg(windows)'.dependencies]
22+
windows = { version = "0.52", features = ["Win32_Foundation", "Win32_Graphics_Printing"] }
23+
2124
[dev-dependencies]
2225
trybuild = "1.0.110"
2326
uuid = { version = "1.17.0", features = ["v4"] }

paperjet/src/print/windows/native.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,59 @@
1+
use std::collections::HashMap;
12
use std::io::Read;
3+
use std::slice;
4+
5+
use windows::Win32::Graphics::Printing::{self, EnumPrintersW};
26

37
use crate::error::PrintError;
48
use crate::options::PrintOptions;
59
use crate::{CrossPlatformApi, PlatformSpecificApi, Printer};
610

711
impl CrossPlatformApi for PlatformSpecificApi {
812
fn get_printers() -> Vec<Printer> {
9-
todo!("Not supported on Windows yet")
13+
let mut buf_size = 0u32;
14+
let mut printers_len = 0u32;
15+
16+
// First call to determine the buffer size (we use level 4 here, thus this is fast)
17+
// SAFETY: the only pointers we pass in are `buf_size` and `printers_len`, which are valid.
18+
let _ = unsafe {
19+
EnumPrintersW(
20+
Printing::PRINTER_ENUM_LOCAL | Printing::PRINTER_ENUM_CONNECTIONS,
21+
None,
22+
4,
23+
None,
24+
&mut buf_size,
25+
&mut printers_len,
26+
)
27+
};
28+
// Second call to populate the buffer
29+
// SAFETY: all pointers we pass in are valid again, and `buf` is of required size, as determined
30+
// by the previous call to `EnumPrintersW`.
31+
let mut buf = vec![0u8; buf_size as usize];
32+
let result = unsafe {
33+
EnumPrintersW(
34+
Printing::PRINTER_ENUM_LOCAL | Printing::PRINTER_ENUM_CONNECTIONS,
35+
None,
36+
4,
37+
Some(&mut buf),
38+
&mut buf_size,
39+
&mut printers_len,
40+
)
41+
};
42+
43+
if result.is_err() {
44+
// TODO: return result
45+
return vec![];
46+
}
47+
48+
unsafe {
49+
slice::from_raw_parts(
50+
buf.as_ptr() as *mut Printing::PRINTER_INFO_4W,
51+
printers_len as usize,
52+
)
53+
}
54+
.iter()
55+
.map(map_printer_info_4_to_printer)
56+
.collect::<Vec<_>>()
1057
}
1158

1259
fn get_printer(_name: &str) -> Option<Printer> {
@@ -25,3 +72,14 @@ impl CrossPlatformApi for PlatformSpecificApi {
2572
todo!("Not supported on Windows yet")
2673
}
2774
}
75+
76+
/// Converts the [`PRINTER_INFO_4W`] instance to a [`Printer`] instance.
77+
fn map_printer_info_4_to_printer(info: &Printing::PRINTER_INFO_4W) -> Printer {
78+
Printer {
79+
identifier: unsafe { info.pPrinterName.to_string().unwrap() },
80+
name: unsafe { info.pPrinterName.to_string().unwrap() },
81+
instance: None,
82+
is_default: false,
83+
options: HashMap::new(),
84+
}
85+
}

0 commit comments

Comments
 (0)