forked from alexbrainman/printer
/
printer.go
132 lines (115 loc) · 3.57 KB
/
printer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Windows printing.
package printer
import (
"syscall"
"unsafe"
)
//go:generate go run mksyscall_windows.go -output zapi.go printer.go
type DOC_INFO_1 struct {
DocName *uint16
OutputFile *uint16
Datatype *uint16
}
type PRINTER_INFO_5 struct {
PrinterName *uint16
PortName *uint16
Attributes uint32
DeviceNotSelectedTimeout uint32
TransmissionRetryTimeout uint32
}
const (
PRINTER_ENUM_LOCAL = 2
PRINTER_ENUM_CONNECTIONS = 4
)
//sys GetDefaultPrinter(buf *uint16, bufN *uint32) (err error) = winspool.GetDefaultPrinterW
//sys ClosePrinter(h syscall.Handle) (err error) = winspool.ClosePrinter
//sys OpenPrinter(name *uint16, h *syscall.Handle, defaults uintptr) (err error) = winspool.OpenPrinterW
//sys StartDocPrinter(h syscall.Handle, level uint32, docinfo *DOC_INFO_1) (err error) = winspool.StartDocPrinterW
//sys EndDocPrinter(h syscall.Handle) (err error) = winspool.EndDocPrinter
//sys WritePrinter(h syscall.Handle, buf *byte, bufN uint32, written *uint32) (err error) = winspool.WritePrinter
//sys StartPagePrinter(h syscall.Handle) (err error) = winspool.StartPagePrinter
//sys EndPagePrinter(h syscall.Handle) (err error) = winspool.EndPagePrinter
//sys EnumPrinters(flags uint32, name *uint16, level uint32, buf *byte, bufN uint32, needed *uint32, returned *uint32) (err error) = winspool.EnumPrintersW
func Default() (string, error) {
b := make([]uint16, 3)
n := uint32(len(b))
err := GetDefaultPrinter(&b[0], &n)
if err != nil {
if err != syscall.ERROR_INSUFFICIENT_BUFFER {
return "", err
}
b = make([]uint16, n)
err = GetDefaultPrinter(&b[0], &n)
if err != nil {
return "", err
}
}
return syscall.UTF16ToString(b), nil
}
// ReadNames return printer names on the system
func ReadNames() ([]string, error) {
const flags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS
var needed, returned uint32
buf := make([]byte, 1)
err := EnumPrinters(flags, nil, 5, &buf[0], uint32(len(buf)), &needed, &returned)
if err != nil {
if err != syscall.ERROR_INSUFFICIENT_BUFFER {
return nil, err
}
buf = make([]byte, needed)
err = EnumPrinters(flags, nil, 5, &buf[0], uint32(len(buf)), &needed, &returned)
if err != nil {
return nil, err
}
}
ps := (*[1024]PRINTER_INFO_5)(unsafe.Pointer(&buf[0]))[:returned]
names := make([]string, 0, returned)
for _, p := range ps {
v := (*[1024]uint16)(unsafe.Pointer(p.PrinterName))[:]
names = append(names, syscall.UTF16ToString(v))
}
return names, nil
}
type Printer struct {
h syscall.Handle
}
func Open(name string) (*Printer, error) {
var p Printer
// TODO: implement pDefault parameter
err := OpenPrinter(&(syscall.StringToUTF16(name))[0], &p.h, 0)
if err != nil {
return nil, err
}
return &p, nil
}
func (p *Printer) StartDocument(name, datatype string) error {
d := DOC_INFO_1{
DocName: &(syscall.StringToUTF16(name))[0],
OutputFile: nil,
Datatype: &(syscall.StringToUTF16(datatype))[0],
}
return StartDocPrinter(p.h, 1, &d)
}
func (p *Printer) Write(b []byte) (int, error) {
var written uint32
err := WritePrinter(p.h, &b[0], uint32(len(b)), &written)
if err != nil {
return 0, err
}
return int(written), nil
}
func (p *Printer) EndDocument() error {
return EndDocPrinter(p.h)
}
func (p *Printer) StartPage() error {
return StartPagePrinter(p.h)
}
func (p *Printer) EndPage() error {
return EndPagePrinter(p.h)
}
func (p *Printer) Close() error {
return ClosePrinter(p.h)
}