@@ -26,9 +26,39 @@ type PRINTER_INFO_5 struct {
26
26
TransmissionRetryTimeout uint32
27
27
}
28
28
29
+ type DRIVER_INFO_8 struct {
30
+ Version uint32
31
+ Name * uint16
32
+ Environment * uint16
33
+ DriverPath * uint16
34
+ DataFile * uint16
35
+ ConfigFile * uint16
36
+ HelpFile * uint16
37
+ DependentFiles * uint16
38
+ MonitorName * uint16
39
+ DefaultDataType * uint16
40
+ PreviousNames * uint16
41
+ DriverDate syscall.Filetime
42
+ DriverVersion uint64
43
+ MfgName * uint16
44
+ OEMUrl * uint16
45
+ HardwareID * uint16
46
+ Provider * uint16
47
+ PrintProcessor * uint16
48
+ VendorSetup * uint16
49
+ ColorProfiles * uint16
50
+ InfPath * uint16
51
+ PrinterDriverAttributes uint32
52
+ CoreDriverDependencies * uint16
53
+ MinInboxDriverVerDate syscall.Filetime
54
+ MinInboxDriverVerVersion uint32
55
+ }
56
+
29
57
const (
30
58
PRINTER_ENUM_LOCAL = 2
31
59
PRINTER_ENUM_CONNECTIONS = 4
60
+
61
+ PRINTER_DRIVER_XPS = 0x00000002
32
62
)
33
63
34
64
//sys GetDefaultPrinter(buf *uint16, bufN *uint32) (err error) = winspool.GetDefaultPrinterW
@@ -40,6 +70,7 @@ const (
40
70
//sys StartPagePrinter(h syscall.Handle) (err error) = winspool.StartPagePrinter
41
71
//sys EndPagePrinter(h syscall.Handle) (err error) = winspool.EndPagePrinter
42
72
//sys EnumPrinters(flags uint32, name *uint16, level uint32, buf *byte, bufN uint32, needed *uint32, returned *uint32) (err error) = winspool.EnumPrintersW
73
+ //sys GetPrinterDriver(h syscall.Handle, env *uint16, level uint32, di *byte, n uint32, needed *uint32) (err error) = winspool.GetPrinterDriverW
43
74
44
75
func Default () (string , error ) {
45
76
b := make ([]uint16 , 3 )
@@ -97,6 +128,40 @@ func Open(name string) (*Printer, error) {
97
128
return & p , nil
98
129
}
99
130
131
+ // DriverInfo stores information about printer driver.
132
+ type DriverInfo struct {
133
+ Name string
134
+ Environment string
135
+ DriverPath string
136
+ Attributes uint32
137
+ }
138
+
139
+ // DriverInfo returns information about printer p driver.
140
+ func (p * Printer ) DriverInfo () (* DriverInfo , error ) {
141
+ var needed uint32
142
+ b := make ([]byte , 1024 * 10 )
143
+ for {
144
+ err := GetPrinterDriver (p .h , nil , 8 , & b [0 ], uint32 (len (b )), & needed )
145
+ if err == nil {
146
+ break
147
+ }
148
+ if err != syscall .ERROR_INSUFFICIENT_BUFFER {
149
+ return nil , err
150
+ }
151
+ if needed <= uint32 (len (b )) {
152
+ return nil , err
153
+ }
154
+ b = make ([]byte , needed )
155
+ }
156
+ di := (* DRIVER_INFO_8 )(unsafe .Pointer (& b [0 ]))
157
+ return & DriverInfo {
158
+ Attributes : di .PrinterDriverAttributes ,
159
+ Name : syscall .UTF16ToString ((* [2048 ]uint16 )(unsafe .Pointer (di .Name ))[:]),
160
+ DriverPath : syscall .UTF16ToString ((* [2048 ]uint16 )(unsafe .Pointer (di .DriverPath ))[:]),
161
+ Environment : syscall .UTF16ToString ((* [2048 ]uint16 )(unsafe .Pointer (di .Environment ))[:]),
162
+ }, nil
163
+ }
164
+
100
165
func (p * Printer ) StartDocument (name , datatype string ) error {
101
166
d := DOC_INFO_1 {
102
167
DocName : & (syscall .StringToUTF16 (name ))[0 ],
@@ -106,6 +171,22 @@ func (p *Printer) StartDocument(name, datatype string) error {
106
171
return StartDocPrinter (p .h , 1 , & d )
107
172
}
108
173
174
+ // StartRawDocument calls StartDocument and passes either "RAW" or "XPS_PASS"
175
+ // as a document type, depending if printer driver is XPS-based or not.
176
+ func (p * Printer ) StartRawDocument (name string ) error {
177
+ di , err := p .DriverInfo ()
178
+ if err != nil {
179
+ return err
180
+ }
181
+ // See https://support.microsoft.com/en-us/help/2779300/v4-print-drivers-using-raw-mode-to-send-pcl-postscript-directly-to-the
182
+ // for details.
183
+ datatype := "RAW"
184
+ if di .Attributes & PRINTER_DRIVER_XPS != 0 {
185
+ datatype = "XPS_PASS"
186
+ }
187
+ return p .StartDocument (name , datatype )
188
+ }
189
+
109
190
func (p * Printer ) Write (b []byte ) (int , error ) {
110
191
var written uint32
111
192
err := WritePrinter (p .h , & b [0 ], uint32 (len (b )), & written )
0 commit comments