Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/qz/printer/status/StatusMonitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public synchronized static boolean launchNotificationThreads() {
for (Winspool.PRINTER_INFO_2 printer : printers) {
printerNameList.add(printer.pPrinterName);
if (!notificationThreadCollection.containsKey(printer.pPrinterName)) {
Thread notificationThread = new WmiPrinterStatusThread(printer.pPrinterName);
boolean holdsJobs = (printer.Attributes & Winspool.PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS) > 0;
Thread notificationThread = new WmiPrinterStatusThread(printer.pPrinterName, holdsJobs);
notificationThreadCollection.put(printer.pPrinterName, notificationThread);
notificationThread.start();
}
Expand Down
36 changes: 26 additions & 10 deletions src/qz/printer/status/WmiPrinterStatusThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class WmiPrinterStatusThread extends Thread {
private final Winspool spool = Winspool.INSTANCE;
private int lastPrinterStatus = -1;
private boolean wasOk = false;
private boolean holdsJobs = false;
private boolean holdsJobs;

private WinNT.HANDLE hChangeObject;
private WinDef.DWORDByReference pdwChangeResult;
Expand Down Expand Up @@ -50,9 +50,23 @@ public class WmiPrinterStatusThread extends Thread {
Winspool.PRINTER_NOTIFY_OPTIONS listenOptions;
Winspool.PRINTER_NOTIFY_OPTIONS statusOptions;

public WmiPrinterStatusThread(String name) {
// Honor translated strings, if available
private static final ArrayList<String> invalidNames = new ArrayList<>();
static {
try {
invalidNames.add(User32Util.loadString("%SystemRoot%\\system32\\localspl.dll,108"));
invalidNames.add(User32Util.loadString("%SystemRoot%\\system32\\localspl.dll,107"));
} catch(Exception e) {
log.warn("Unable to obtain strings, defaulting to en-US values.", e);
invalidNames.add("Local Downlevel Document");
invalidNames.add("Remote Downlevel Document");
}
}

public WmiPrinterStatusThread(String name, boolean holdsJobs) {
super("Printer Status Monitor " + name);
printerName = name;
this.holdsJobs = holdsJobs;

listenOptions = new Winspool.PRINTER_NOTIFY_OPTIONS();
listenOptions.Version = 2;
Expand Down Expand Up @@ -100,14 +114,6 @@ private void attachToSystem() {
WinNT.HANDLEByReference phPrinterObject = new WinNT.HANDLEByReference();
spool.OpenPrinter(printerName, phPrinterObject, null);

// Determine if the printer deletes jobs after printing
// todo this should probably be done once, instead of once for every printer thread
for (Winspool.PRINTER_INFO_2 printerInfo : WinspoolUtil.getPrinterInfo2()) {
if (printerInfo.pPrinterName.equals(printerName)) {
holdsJobs = (printerInfo.Attributes & Winspool.PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS) > 0;
}
}

pdwChangeResult = new WinDef.DWORDByReference();
//The second param determines what kind of event releases our lock
//See https://msdn.microsoft.com/en-us/library/windows/desktop/dd162722(v=vs.85).aspx
Expand Down Expand Up @@ -192,6 +198,16 @@ private void sendPendingStatuses() {
ArrayList<Integer> codes = jobCodesEntry.getValue();
int jobId = jobCodesEntry.getKey();

// Wait until we have a real docName
if (invalidNames.contains(docNames.get(jobId))) continue;

// Workaround for double 'printed' statuses
if (holdsJobs && docNames.get(jobId) == null && codes.size() == 1 && codes.get(0) == (int)WmiJobStatusMap.PRINTED.getRawCode()) {
i.remove();
lastJobStatusCodes.remove(jobId);
continue;
}

for (int code: codes) {
int newStatusCode = code;
int oldStatusCode = lastJobStatusCodes.getOrDefault(jobId, 0);
Expand Down
2 changes: 1 addition & 1 deletion src/qz/printer/status/job/NativeJobStatus.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public enum NativeJobStatus implements NativeStatus {
PAPEROUT(Level.WARN),
RETAINED(Level.INFO),
PAUSED(Level.WARN),
PRINTED(Level.INFO),
SENT(Level.INFO),
RESTART(Level.WARN),
RENDERING_LOCALLY(Level.INFO),
USER_INTERVENTION(Level.WARN),
Expand Down
2 changes: 1 addition & 1 deletion src/qz/printer/status/job/WmiJobStatusMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public enum WmiJobStatusMap implements NativeStatus.NativeMap {
DELETED(NativeJobStatus.DELETED, 0x00000100), // Job has been deleted
BLOCKED_DEVQ(NativeJobStatus.ABORTED, 0x00000200), // The driver cannot print the job
RESTART(NativeJobStatus.RESTART, 0x00000800), // Job has been restarted
COMPLETE(NativeJobStatus.PRINTED, 0x00001000), // Windows XP and later: Job is sent to the printer, but the job may not be printed yet
COMPLETE(NativeJobStatus.SENT, 0x00001000), // Windows XP and later: Job is sent to the printer, but the job may not be printed yet
RETAINED(NativeJobStatus.RETAINED, 0x00002000), // Windows Vista and later: Job has been retained in the print queue and cannot be deleted
RENDERING_LOCALLY(NativeJobStatus.RENDERING_LOCALLY, 0x00004000), // Job rendering locally on the client
USER_INTERVENTION(NativeJobStatus.USER_INTERVENTION, 0x40000000); // Printer has an error that requires the user to do something
Expand Down