2
Copyright (C) 2009 Volker Berlin (i-net software)
3
Copyright (C) 2010 Karsten Heinrich (i-net software)
5
This software is provided 'as-is', without any express or implied
6
warranty. In no event will the authors be held liable for any damages
7
arising from the use of this software.
9
Permission is granted to anyone to use this software for any purpose,
10
including commercial applications, and to alter it and redistribute it
11
freely, subject to the following restrictions:
13
1. The origin of this software must not be misrepresented; you must not
14
claim that you wrote the original software. If you use this software
15
in a product, an acknowledgment in the product documentation would be
16
appreciated but is not required.
17
2. Altered source versions must be plainly marked as such, and must not be
18
misrepresented as being the original software.
19
3. This notice may not be removed or altered from any source distribution.
27
using System.Runtime.InteropServices;
28
using Microsoft.Win32.SafeHandles;
29
using System.Drawing.Printing;
31
namespace ikvm.awt.printing
34
/// Base Implementation of the PrintPeer
36
abstract class BasePrintPeer : sun.print.PrintPeer
38
public virtual Object getPrinterStatus(String PrinterName, java.lang.Class category)
43
public String getDefaultPrinterName()
45
return new PrinterSettings().PrinterName;
48
public String[] getAllPrinterNames()
50
PrinterSettings.StringCollection printers = PrinterSettings.InstalledPrinters;
51
String[] result = new String[printers.Count];
52
printers.CopyTo(result, 0);
56
public java.awt.Graphics2D createGraphics(System.Drawing.Graphics g)
58
return new PrintGraphics(g);
63
/// Implementation of the PrintPeer for Linux
65
class LinuxPrintPeer : BasePrintPeer
70
/// Implementation of the PrintPeer for Windows
72
class Win32PrintPeer : BasePrintPeer
74
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
75
private struct PRINTER_INFO_2
77
[MarshalAs(UnmanagedType.LPTStr)]
78
public string pServerName;
79
[MarshalAs(UnmanagedType.LPTStr)]
80
public string pPrinterName;
81
[MarshalAs(UnmanagedType.LPTStr)]
82
public string pShareName;
83
[MarshalAs(UnmanagedType.LPTStr)]
84
public string pPortName;
85
[MarshalAs(UnmanagedType.LPTStr)]
86
public string pDriverName;
87
[MarshalAs(UnmanagedType.LPTStr)]
88
public string pComment;
89
[MarshalAs(UnmanagedType.LPTStr)]
90
public string pLocation;
91
public IntPtr pDevMode;
92
[MarshalAs(UnmanagedType.LPTStr)]
93
public string pSepFile;
94
[MarshalAs(UnmanagedType.LPTStr)]
95
public string pPrintProcessor;
96
[MarshalAs(UnmanagedType.LPTStr)]
97
public string pDatatype;
98
[MarshalAs(UnmanagedType.LPTStr)]
99
public string pParameters;
100
public IntPtr pSecurityDescriptor;
101
public uint Attributes;
102
public uint Priority;
103
public uint DefaultPriority;
104
public uint StartTime;
105
public uint UntilTime;
108
public uint AveragePPM;
111
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
112
private static extern bool GetPrinter(SafePrinterHandle hPrinter, int dwLevel, IntPtr pPrinter, int cbBuf, out int pcbNeeded);
114
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
115
private static extern bool OpenPrinter(string pPrinterName, out SafePrinterHandle hPrinter, IntPtr pDefault);
117
private const int ERROR_INSUFFICIENT_BUFFER = 122;
119
private const int PRINTER_STATUS_PAUSED = 0x1;
120
private const int PRINTER_STATUS_ERROR = 0x2; // MSDN says that this value is not used
121
private const int PRINTER_STATUS_PENDING_DELETION = 0x4;
122
private const int PRINTER_STATUS_PAPER_JAM = 0x8;
123
private const int PRINTER_STATUS_PAPER_OUT = 0x10;
124
private const int PRINTER_STATUS_MANUAL_FEED = 0x20;
125
private const int PRINTER_STATUS_PAPER_PROBLEM = 0x40;
126
private const int PRINTER_STATUS_OFFLINE = 0x80;
127
private const int PRINTER_STATUS_IO_ACTIVE = 0x100;
128
private const int PRINTER_STATUS_BUSY = 0x200;
129
private const int PRINTER_STATUS_PRINTING = 0x400;
130
private const int PRINTER_STATUS_OUTPUT_BIN_FULL = 0x800;
131
private const int PRINTER_STATUS_NOT_AVAILABLE = 0x1000;
132
private const int PRINTER_STATUS_WAITING = 0x2000;
133
private const int PRINTER_STATUS_PROCESSING = 0x4000;
134
private const int PRINTER_STATUS_INITIALIZING = 0x8000;
135
private const int PRINTER_STATUS_WARMING_UP = 0x10000;
136
private const int PRINTER_STATUS_TONER_LOW = 0x20000;
137
private const int PRINTER_STATUS_NO_TONER = 0x40000;
138
private const int PRINTER_STATUS_PAGE_PUNT = 0x80000;
139
private const int PRINTER_STATUS_USER_INTERVENTION = 0x100000;
140
private const int PRINTER_STATUS_OUT_OF_MEMORY = 0x200000;
141
private const int PRINTER_STATUS_DOOR_OPEN = 0x400000;
142
private const int PRINTER_STATUS_SERVER_UNKNOWN = 0x800000;
143
private const int PRINTER_STATUS_POWER_SAVE = 0x1000000;
146
/// Get a printer status
148
/// <param name="printerName">a valid printer name</param>
149
/// <param name="category">a category that should request</param>
150
/// <returns>a printer attribute or null</returns>
151
public override Object getPrinterStatus(String printerName, java.lang.Class category)
155
if (GetPrinterInfo2(printerName, out cJobs, out status))
157
if (category == (java.lang.Class)typeof(javax.print.attribute.standard.PrinterState))
160
(PRINTER_STATUS_ERROR | PRINTER_STATUS_NO_TONER | PRINTER_STATUS_OUT_OF_MEMORY |
161
PRINTER_STATUS_OFFLINE | PRINTER_STATUS_USER_INTERVENTION |
162
PRINTER_STATUS_DOOR_OPEN | PRINTER_STATUS_NOT_AVAILABLE )) > 0)
164
return javax.print.attribute.standard.PrinterState.STOPPED;
166
if( (status & (PRINTER_STATUS_BUSY | PRINTER_STATUS_PRINTING ))> 0 )
168
return javax.print.attribute.standard.PrinterState.PROCESSING;
171
// null seems to be the default instead of unknown - UNKOWN ist not used in the reference RT
172
// javax.print.attribute.standard.PrinterState.UNKNOWN;
174
if (category == (java.lang.Class)typeof(javax.print.attribute.standard.PrinterStateReasons))
176
return extractResions(status);
178
if (category == (java.lang.Class)typeof(javax.print.attribute.standard.QueuedJobCount))
180
return new javax.print.attribute.standard.QueuedJobCount(cJobs);
182
if (category == (java.lang.Class)typeof(javax.print.attribute.standard.PrinterIsAcceptingJobs))
185
(PRINTER_STATUS_ERROR |
186
PRINTER_STATUS_NO_TONER |
187
PRINTER_STATUS_OUT_OF_MEMORY |
188
PRINTER_STATUS_OFFLINE |
189
PRINTER_STATUS_USER_INTERVENTION |
190
PRINTER_STATUS_DOOR_OPEN)) > 0)
192
return javax.print.attribute.standard.PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS;
196
return javax.print.attribute.standard.PrinterIsAcceptingJobs.ACCEPTING_JOBS;
203
private javax.print.attribute.standard.PrinterStateReasons extractResions(int status)
205
javax.print.attribute.standard.PrinterStateReasons reasons = new javax.print.attribute.standard.PrinterStateReasons();
206
if ((status & PRINTER_STATUS_PAUSED) > 0)
208
reasons.put(javax.print.attribute.standard.PrinterStateReason.PAUSED, javax.print.attribute.standard.Severity.REPORT);
210
if ((status & PRINTER_STATUS_ERROR) > 0)
212
reasons.put(javax.print.attribute.standard.PrinterStateReason.OTHER, javax.print.attribute.standard.Severity.ERROR);
214
if ((status & PRINTER_STATUS_PENDING_DELETION) > 0) { }
215
if ((status & PRINTER_STATUS_PAPER_JAM) > 0)
217
reasons.put(javax.print.attribute.standard.PrinterStateReason.MEDIA_JAM, javax.print.attribute.standard.Severity.WARNING);
219
if ((status & PRINTER_STATUS_PAPER_OUT) > 0)
221
reasons.put(javax.print.attribute.standard.PrinterStateReason.MEDIA_EMPTY, javax.print.attribute.standard.Severity.WARNING);
223
if ((status & PRINTER_STATUS_MANUAL_FEED) > 0) { }
224
if ((status & PRINTER_STATUS_PAPER_PROBLEM) > 0) {}
225
if ((status & PRINTER_STATUS_OFFLINE) > 0) {
226
reasons.put(javax.print.attribute.standard.PrinterStateReason.TIMED_OUT, javax.print.attribute.standard.Severity.ERROR);
228
if ((status & PRINTER_STATUS_IO_ACTIVE) > 0) { }
229
if ((status & PRINTER_STATUS_BUSY) > 0) { }
230
if ((status & PRINTER_STATUS_PRINTING) > 0) { }
231
if ((status & PRINTER_STATUS_OUTPUT_BIN_FULL) > 0) {
232
reasons.put(javax.print.attribute.standard.PrinterStateReason.OUTPUT_AREA_FULL, javax.print.attribute.standard.Severity.WARNING);
234
if ((status & PRINTER_STATUS_NOT_AVAILABLE) > 0) { }
235
if ((status & PRINTER_STATUS_WAITING) > 0) { }
236
if ((status & PRINTER_STATUS_PROCESSING) > 0) { }
237
if ((status & PRINTER_STATUS_INITIALIZING) > 0) { }
238
if ((status & PRINTER_STATUS_WARMING_UP) > 0) { }
239
if ((status & PRINTER_STATUS_TONER_LOW) > 0) {
240
reasons.put(javax.print.attribute.standard.PrinterStateReason.TONER_LOW, javax.print.attribute.standard.Severity.WARNING);
242
if ((status & PRINTER_STATUS_NO_TONER) > 0) {
243
reasons.put(javax.print.attribute.standard.PrinterStateReason.TONER_EMPTY, javax.print.attribute.standard.Severity.ERROR);
245
if ((status & PRINTER_STATUS_PAGE_PUNT) > 0) { }
246
if ((status & PRINTER_STATUS_USER_INTERVENTION) > 0) {
247
reasons.put(javax.print.attribute.standard.PrinterStateReason.OTHER, javax.print.attribute.standard.Severity.ERROR);
249
if ((status & PRINTER_STATUS_OUT_OF_MEMORY) > 0) {
250
reasons.put(javax.print.attribute.standard.PrinterStateReason.OTHER, javax.print.attribute.standard.Severity.ERROR);
252
if ((status & PRINTER_STATUS_DOOR_OPEN) > 0) {
253
reasons.put(javax.print.attribute.standard.PrinterStateReason.DOOR_OPEN, javax.print.attribute.standard.Severity.ERROR);
255
if ((status & PRINTER_STATUS_SERVER_UNKNOWN) > 0) { }
256
if ((status & PRINTER_STATUS_POWER_SAVE) > 0) {
257
reasons.put(javax.print.attribute.standard.PrinterStateReason.PAUSED, javax.print.attribute.standard.Severity.REPORT);
259
return reasons.isEmpty() ? null : reasons;
263
/// Get infos from the PRINTER_INFO_2 struc
265
/// <param name="printerName">The name of a valid printer</param>
266
/// <param name="cJobs">returns the current count of print jobs</param>
267
/// <param name="status">returns the current status of the printer</param>
268
/// <returns>true if the return is valid</returns>
269
[System.Security.SecuritySafeCritical]
270
private static bool GetPrinterInfo2(string printerName, out int cJobs, out int status)
272
SafePrinterHandle printer = null;
276
if (OpenPrinter(printerName, out printer, IntPtr.Zero)
277
&& !GetPrinter(printer, 2, IntPtr.Zero, 0, out needed))
279
int lastWin32Error = Marshal.GetLastWin32Error();
280
if (lastWin32Error == ERROR_INSUFFICIENT_BUFFER)
282
IntPtr pPrinter = Marshal.AllocHGlobal((int)needed);
285
if (GetPrinter(printer, 2, pPrinter, needed, out needed))
287
PRINTER_INFO_2 printerInfo2 = (PRINTER_INFO_2)Marshal.PtrToStructure(pPrinter, typeof(PRINTER_INFO_2));
288
cJobs = printerInfo2.cJobs;
289
status = printerInfo2.Status;
295
Marshal.FreeHGlobal(pPrinter);
314
[System.Security.SecurityCritical]
315
sealed class SafePrinterHandle : SafeHandleZeroOrMinusOneIsInvalid
317
[DllImport("winspool.drv")]
318
private static extern bool ClosePrinter(IntPtr hPrinter);
320
private SafePrinterHandle()
325
[System.Security.SecurityCritical]
326
protected override bool ReleaseHandle()
328
return ClosePrinter(handle);