11use std:: collections:: HashMap ;
22use std:: io:: Read ;
3- use std:: slice;
3+ use std:: { ptr , slice} ;
44
5- use windows:: Win32 :: Graphics :: Printing :: { self , EnumPrintersW } ;
5+ use windows:: Win32 :: Graphics :: Printing ;
6+ use windows:: core:: PWSTR ;
67
78use crate :: error:: PrintError ;
89use crate :: options:: PrintOptions ;
@@ -16,7 +17,7 @@ impl CrossPlatformApi for PlatformSpecificApi {
1617 // First call to determine the buffer size (we use level 4 here, thus this is fast)
1718 // SAFETY: the only pointers we pass in are `buf_size` and `printers_len`, which are valid.
1819 let _ = unsafe {
19- EnumPrintersW (
20+ Printing :: EnumPrintersW (
2021 Printing :: PRINTER_ENUM_LOCAL | Printing :: PRINTER_ENUM_CONNECTIONS ,
2122 None ,
2223 4 ,
@@ -30,10 +31,10 @@ impl CrossPlatformApi for PlatformSpecificApi {
3031 // by the previous call to `EnumPrintersW`.
3132 let mut buf = vec ! [ 0u8 ; buf_size as usize ] ;
3233 let result = unsafe {
33- EnumPrintersW (
34+ Printing :: EnumPrintersW (
3435 Printing :: PRINTER_ENUM_LOCAL | Printing :: PRINTER_ENUM_CONNECTIONS ,
3536 None ,
36- 5 ,
37+ 4 ,
3738 Some ( & mut buf) ,
3839 & mut buf_size,
3940 & mut printers_len,
@@ -51,7 +52,7 @@ impl CrossPlatformApi for PlatformSpecificApi {
5152 printers_len as usize ,
5253 )
5354 . iter ( )
54- . map ( map_printer_info_4_to_printer)
55+ . map ( |info4| map_printer_info_4_to_printer ( info4 ) )
5556 . collect :: < Result < Vec < _ > , _ > > ( )
5657 }
5758 }
@@ -61,7 +62,29 @@ impl CrossPlatformApi for PlatformSpecificApi {
6162 }
6263
6364 fn get_default_printer ( ) -> Option < Printer > {
64- todo ! ( "Not supported on Windows yet" )
65+ let mut len = 0 ;
66+
67+ // First call to determine the string length
68+ // SAFETY: the first argument can be a null pointer, and the second is a valid pointer to an
69+ // integer.
70+ let _ = unsafe { Printing :: GetDefaultPrinterW ( PWSTR ( ptr:: null_mut ( ) ) , & mut len) } ;
71+
72+ // Second call to fill the buffer with the string bytes
73+ // SAFETY: both pointers are valid and will be populated with valid contents by Windows.
74+ let mut buf = vec ! [ 0u16 ; len as usize ] ;
75+ let status = unsafe { Printing :: GetDefaultPrinterW ( PWSTR ( buf. as_mut_ptr ( ) ) , & mut len) } ;
76+ if !status. as_bool ( ) {
77+ return None ;
78+ }
79+
80+ let name = String :: from_utf16_lossy ( & buf[ ..( buf. len ( ) - 1 ) ] ) ;
81+ Some ( Printer {
82+ identifier : name. clone ( ) ,
83+ name,
84+ instance : None ,
85+ is_default : true ,
86+ options : HashMap :: new ( ) ,
87+ } )
6588 }
6689
6790 fn print < I , R > ( _readers : I , _printer : Printer , _options : PrintOptions ) -> Result < ( ) , PrintError >
@@ -74,10 +97,24 @@ impl CrossPlatformApi for PlatformSpecificApi {
7497}
7598
7699/// Converts the [`PRINTER_INFO_4W`] instance to a [`Printer`] instance.
77- fn map_printer_info_4_to_printer ( info : & Printing :: PRINTER_INFO_4W ) -> Result < Printer , PrintError > {
100+ ///
101+ /// # Safety
102+ /// `info` must be a valid reference to a valid `PRINTER_INFO_4W`.
103+ unsafe fn map_printer_info_4_to_printer (
104+ info : & Printing :: PRINTER_INFO_4W ,
105+ ) -> Result < Printer , PrintError > {
106+ // SAFETY: info is a valid `PRINTER_INFO_4W` instance, as per the precondition.
107+ let identifier = unsafe { info. pPrinterName . to_string ( ) ? } ;
108+
109+ if let Some ( default_printer) = crate :: get_default_printer ( ) {
110+ if default_printer. identifier == identifier {
111+ return Ok ( default_printer) ;
112+ }
113+ } ;
114+
78115 Ok ( Printer {
79- identifier : unsafe { info . pPrinterName . to_string ( ) ? } ,
80- name : unsafe { info . pPrinterName . to_string ( ) ? } ,
116+ identifier : identifier . clone ( ) ,
117+ name : identifier ,
81118 instance : None ,
82119 is_default : false ,
83120 options : HashMap :: new ( ) ,
0 commit comments