2 * lpr for cygwin/windows
4 * Copyright (C) 2000-2003 Rick Rankin
5 * http://www.cygwin.com/ml/cygwin/2000-07/msg00320.html
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation in version 2 of the License.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "src/lpr/Printer.hh"
22 #include "src/lpr/Win32Utils.hh"
24 inline LPTSTR
tstr(const string
& str
)
26 return const_cast<char*>(str
.c_str());
29 Printer::Printer(const string
&name
, bool debugFlag
)
30 throw(PrinterException
)
32 m_debugFlag(debugFlag
),
33 m_devHandle(INVALID_HANDLE_VALUE
),
39 m_buffer
= new unsigned char[m_bufferSize
];
44 // Initialize the DEVMODE structure
45 // Get the amount of space needed for the buffer.
46 DWORD needed
= DocumentProperties(NULL
, m_devHandle
, tstr(m_devName
),
49 m_devMode
= reinterpret_cast<DEVMODE
*>(new unsigned char[needed
]);
51 // Get the default DEVMODE for the printer.
52 DWORD ret
= DocumentProperties(NULL
, m_devHandle
, tstr(m_devName
),
53 m_devMode
, NULL
, DM_OUT_BUFFER
);
55 throw PrinterException("error getting the default device mode: " +
56 Win32Utils::getErrorMessage());
58 // Close the printer, because we'll need to reopen it later, passing it
59 // the DEVMODE structure with any optional changes by the user.
74 if (m_devHandle
!= INVALID_HANDLE_VALUE
)
76 ClosePrinter(m_devHandle
);
77 m_devHandle
= INVALID_HANDLE_VALUE
;
81 void Printer::endDoc()
82 throw(PrinterException
)
84 if (!EndDocPrinter(m_devHandle
))
85 throw PrinterException("EndDocPrinter error: " +
86 Win32Utils::getErrorMessage());
89 void Printer::endPage()
90 throw(PrinterException
)
92 cout
<< "Printer::endPage()" << endl
;
93 if (!EndPagePrinter(m_devHandle
))
94 throw PrinterException("EndPagePrinter error: " +
95 Win32Utils::getErrorMessage());
98 void Printer::flush(void)
99 throw(PrinterException
)
101 if (m_bufferIndex
> 0)
103 write(m_buffer
, m_bufferIndex
);
108 void Printer::print(istream
& in
, const string
& docName
)
109 throw(PrinterException
)
118 if (ch
== '\n' && lastCh
!= '\r')
127 void Printer::put(unsigned char ch
)
128 throw(PrinterException
)
130 if (m_bufferIndex
== m_bufferSize
)
132 m_buffer
[m_bufferIndex
++] = ch
;
135 void Printer::startDoc(const string
& docName
)
136 throw(PrinterException
)
142 di1
.pDocName
= tstr(docName
);
144 di1
.pDatatype
= "RAW";
146 if (StartDocPrinter(m_devHandle
, 1, (LPBYTE
) &di1
) == 0)
147 throw PrinterException("StartDocPrinter error: " +
148 Win32Utils::getErrorMessage());
151 void Printer::startPage()
152 throw(PrinterException
)
154 cout
<< "Printer::startPage()" << endl
;
155 if (!StartPagePrinter(m_devHandle
))
156 throw PrinterException("StartPagePrinter error: " +
157 Win32Utils::getErrorMessage());
160 void Printer::write(unsigned char *buf
, unsigned int size
)
161 throw(PrinterException
)
164 if (!WritePrinter(m_devHandle
, buf
, size
, &written
))
165 throw PrinterException("error writing to device '" + m_devName
+ "': " +
166 Win32Utils::getErrorMessage());
169 //***************************************************************************
171 // Private operations
173 //***************************************************************************
175 Printer::PrinterList
Printer::enumPrinters(DWORD flags
, LPTSTR name
)
176 throw(PrinterException
)
180 EnumPrinters(flags
, name
, 5, 0, 0, &bytesNeeded
, &numPrinters
);
181 auto_ptr
<BYTE
> enumBuffer(new BYTE
[bytesNeeded
]);
182 if (!EnumPrinters(flags
, name
, 5, enumBuffer
.get(), bytesNeeded
,
183 &bytesNeeded
, &numPrinters
))
184 throw PrinterException("unable to enumerate printers: " +
185 Win32Utils::getErrorMessage());
187 PRINTER_INFO_5
*pi
= reinterpret_cast<PRINTER_INFO_5
*>(enumBuffer
.get());
190 for (unsigned int ii
= 0; ii
< numPrinters
; ++ii
)
193 cerr
<< "Printer name: '" << pi
->pPrinterName
<< "', "
194 << "Port name: '" << pi
->pPortName
<< "'" << endl
;
195 list
.push_back(*pi
++);
201 void Printer::mapPortName()
202 throw(PrinterException
)
206 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
208 bool isWindows9x
= (osvi
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
&&
209 (osvi
.dwMajorVersion
> 4 ||
210 (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
> 0)));
212 bool isWindows2K_NT4
= (osvi
.dwPlatformId
== VER_PLATFORM_WIN32_NT
&&
213 osvi
.dwMajorVersion
>= 4);
216 cout
<< "isWindows9x = " << isWindows9x
<< ", "
217 << "isWindows2K_NT4 = " << isWindows2K_NT4
<< endl
;
222 PrinterList list
= enumPrinters(PRINTER_ENUM_NAME
, "");
223 for (PrinterList::iterator it
= list
.begin(); it
!= list
.end(); ++it
)
225 if (stricmp(m_devName
.c_str(), it
->pPortName
) == 0)
228 cout
<< "Mapped '" << m_devName
<< "' to '" << it
->pPrinterName
230 m_devName
= it
->pPrinterName
;
236 else if (isWindows2K_NT4
)
238 PrinterList list
= enumPrinters(PRINTER_ENUM_LOCAL
, 0);
239 for (PrinterList::iterator it
= list
.begin(); it
!= list
.end(); ++it
)
241 if (stricmp(m_devName
.c_str(), it
->pPortName
) == 0)
244 cout
<< "Mapped '" << m_devName
<< "' to '" << it
->pPrinterName
246 m_devName
= it
->pPrinterName
;
251 list
= enumPrinters(PRINTER_ENUM_CONNECTIONS
, 0);
252 for (PrinterList::iterator it
= list
.begin(); it
!= list
.end(); ++it
)
254 if (stricmp(m_devName
.c_str(), it
->pPortName
) == 0)
257 cout
<< "Mapped '" << m_devName
<< "' to '" << it
->pPrinterName
259 m_devName
= it
->pPrinterName
;
267 throw(PrinterException
)
269 PRINTER_DEFAULTS prDef
;
271 prDef
.pDatatype
= "RAW";
272 prDef
.pDevMode
= m_devMode
;
273 prDef
.DesiredAccess
= PRINTER_ALL_ACCESS
;
275 if (m_devHandle
== INVALID_HANDLE_VALUE
&&
276 !OpenPrinter(tstr(m_devName
), &m_devHandle
, &prDef
))
277 throw PrinterException("can't open '" + m_devName
+ "' for writing: " +
278 Win32Utils::getErrorMessage());