1+ use std:: collections:: HashMap ;
12use std:: io:: Read ;
3+ use std:: slice;
4+
5+ use windows:: Win32 :: Graphics :: Printing :: { self , EnumPrintersW } ;
26
37use crate :: error:: PrintError ;
48use crate :: options:: PrintOptions ;
59use crate :: { CrossPlatformApi , PlatformSpecificApi , Printer } ;
610
711impl 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