diff --git a/contrib/monitordemo/build.xml b/contrib/monitordemo/build.xml
index 79d2322830..cb5ad9e77f 100644
--- a/contrib/monitordemo/build.xml
+++ b/contrib/monitordemo/build.xml
@@ -9,7 +9,7 @@
-
+
diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Winspool.java b/contrib/platform/src/com/sun/jna/platform/win32/Winspool.java
index cf66139e26..7dcdac4cb4 100644
--- a/contrib/platform/src/com/sun/jna/platform/win32/Winspool.java
+++ b/contrib/platform/src/com/sun/jna/platform/win32/Winspool.java
@@ -28,6 +28,7 @@
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.Structure.FieldOrder;
+import com.sun.jna.Union;
import com.sun.jna.platform.win32.WinBase.SYSTEMTIME;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.DWORDByReference;
@@ -36,6 +37,7 @@
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.HANDLEByReference;
import com.sun.jna.ptr.IntByReference;
+import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;
@@ -151,6 +153,72 @@ public interface Winspool extends StdCallLibrary {
public static final int PRINTER_ENUM_ICON8 = 0x00800000;
public static final int PRINTER_ENUM_HIDE = 0x01000000;
+ public static final int PRINTER_NOTIFY_OPTIONS_REFRESH = 0x01;
+
+ public static final int PRINTER_NOTIFY_INFO_DISCARDED = 0x01;
+
+ public static final int PRINTER_NOTIFY_TYPE = 0x00;
+ public static final int JOB_NOTIFY_TYPE = 0x01;
+
+ public static final short PRINTER_NOTIFY_FIELD_SERVER_NAME = 0x00;
+ public static final short PRINTER_NOTIFY_FIELD_PRINTER_NAME = 0x01;
+ public static final short PRINTER_NOTIFY_FIELD_SHARE_NAME = 0x02;
+ public static final short PRINTER_NOTIFY_FIELD_PORT_NAME = 0x03;
+ public static final short PRINTER_NOTIFY_FIELD_DRIVER_NAME = 0x04;
+ public static final short PRINTER_NOTIFY_FIELD_COMMENT = 0x05;
+ public static final short PRINTER_NOTIFY_FIELD_LOCATION = 0x06;
+ public static final short PRINTER_NOTIFY_FIELD_DEVMODE = 0x07;
+ public static final short PRINTER_NOTIFY_FIELD_SEPFILE = 0x08;
+ public static final short PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR = 0x09;
+ public static final short PRINTER_NOTIFY_FIELD_PARAMETERS = 0x0A;
+ public static final short PRINTER_NOTIFY_FIELD_DATATYPE = 0x0B;
+ public static final short PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR = 0x0C;
+ public static final short PRINTER_NOTIFY_FIELD_ATTRIBUTES = 0x0D;
+ public static final short PRINTER_NOTIFY_FIELD_PRIORITY = 0x0E;
+ public static final short PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY = 0x0F;
+ public static final short PRINTER_NOTIFY_FIELD_START_TIME = 0x10;
+ public static final short PRINTER_NOTIFY_FIELD_UNTIL_TIME = 0x11;
+ public static final short PRINTER_NOTIFY_FIELD_STATUS = 0x12;
+ public static final short PRINTER_NOTIFY_FIELD_STATUS_STRING = 0x13;
+ public static final short PRINTER_NOTIFY_FIELD_CJOBS = 0x14;
+ public static final short PRINTER_NOTIFY_FIELD_AVERAGE_PPM = 0x15;
+ public static final short PRINTER_NOTIFY_FIELD_TOTAL_PAGES = 0x16;
+ public static final short PRINTER_NOTIFY_FIELD_PAGES_PRINTED = 0x17;
+ public static final short PRINTER_NOTIFY_FIELD_TOTAL_BYTES = 0x18;
+ public static final short PRINTER_NOTIFY_FIELD_BYTES_PRINTED = 0x19;
+ public static final short PRINTER_NOTIFY_FIELD_OBJECT_GUID = 0x1A;
+ public static final short PRINTER_NOTIFY_FIELD_FRIENDLY_NAME = 0x1B;
+ public static final short PRINTER_NOTIFY_FIELD_BRANCH_OFFICE_PRINTING = 0x1C;
+
+ public static final short JOB_NOTIFY_FIELD_PRINTER_NAME = 0x00;
+ public static final short JOB_NOTIFY_FIELD_MACHINE_NAME = 0x01;
+ public static final short JOB_NOTIFY_FIELD_PORT_NAME = 0x02;
+ public static final short JOB_NOTIFY_FIELD_USER_NAME = 0x03;
+ public static final short JOB_NOTIFY_FIELD_NOTIFY_NAME = 0x04;
+ public static final short JOB_NOTIFY_FIELD_DATATYPE = 0x05;
+ public static final short JOB_NOTIFY_FIELD_PRINT_PROCESSOR = 0x06;
+ public static final short JOB_NOTIFY_FIELD_PARAMETERS = 0x07;
+ public static final short JOB_NOTIFY_FIELD_DRIVER_NAME = 0x08;
+ public static final short JOB_NOTIFY_FIELD_DEVMODE = 0x09;
+ public static final short JOB_NOTIFY_FIELD_STATUS = 0x0A;
+ public static final short JOB_NOTIFY_FIELD_STATUS_STRING = 0x0B;
+ public static final short JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR = 0x0C;
+ public static final short JOB_NOTIFY_FIELD_DOCUMENT = 0x0D;
+ public static final short JOB_NOTIFY_FIELD_PRIORITY = 0x0E;
+ public static final short JOB_NOTIFY_FIELD_POSITION = 0x0F;
+ public static final short JOB_NOTIFY_FIELD_SUBMITTED = 0x10;
+ public static final short JOB_NOTIFY_FIELD_START_TIME = 0x11;
+ public static final short JOB_NOTIFY_FIELD_UNTIL_TIME = 0x12;
+ public static final short JOB_NOTIFY_FIELD_TIME = 0x13;
+ public static final short JOB_NOTIFY_FIELD_TOTAL_PAGES = 0x14;
+ public static final short JOB_NOTIFY_FIELD_PAGES_PRINTED = 0x15;
+ public static final short JOB_NOTIFY_FIELD_TOTAL_BYTES = 0x16;
+ public static final short JOB_NOTIFY_FIELD_BYTES_PRINTED = 0x17;
+ public static final short JOB_NOTIFY_FIELD_REMOTE_JOB_ID = 0x18;
+
+ public static final int PRINTER_NOTIFY_CATEGORY_ALL = 0x001000;
+ public static final int PRINTER_NOTIFY_CATEGORY_3D = 0x002000;
+
/**
* The EnumPrinters function enumerates available printers, print servers,
* domains, or print providers.
@@ -565,6 +633,313 @@ boolean OpenPrinter(
*/
boolean ClosePrinter(HANDLE hPrinter);
+ /**
+ * The PRINTER_NOTIFY_OPTIONS structure specifies options for a change
+ * notification object that monitors a printer or print server.
+ *
+ * @see
+ *
+ * PRINTER_NOTIFY_OPTIONS structure
+ *
+ */
+ @Structure.FieldOrder({ "Version", "Flags", "Count", "pTypes" })
+ public class PRINTER_NOTIFY_OPTIONS extends Structure {
+
+ /**
+ * The version of this structure. Set this member to 2.
+ */
+ public int Version = 2;
+
+ /**
+ * A bit flag. If you set the PRINTER_NOTIFY_OPTIONS_REFRESH flag in a
+ * call to the FindNextPrinterChangeNotification function, the function
+ * provides current data for all monitored printer information fields.
+ * The FindFirstPrinterChangeNotification function ignores the Flags
+ * member.
+ */
+ public int Flags;
+
+ /**
+ * The number of elements in the pTypes array.
+ */
+ public int Count;
+
+ /**
+ * A pointer to an array of PRINTER_NOTIFY_OPTIONS_TYPE structures. Use
+ * one element of this array to specify the printer information fields
+ * to monitor, and one element to specify the job information fields to
+ * monitor. You can monitor either printer information, job
+ * information, or both.
+ */
+ public PRINTER_NOTIFY_OPTIONS_TYPE.ByReference pTypes;
+
+ }
+
+ /**
+ * The PRINTER_NOTIFY_OPTIONS_TYPE structure specifies the set of printer
+ * or job information fields to be monitored by a printer change
+ * notification object.
+ *
+ * @see
+ *
+ * PRINTER_NOTIFY_OPTIONS_TYPE structure
+ *
+ */
+ @Structure.FieldOrder({ "Type", "Reserved0", "Reserved1", "Reserved2",
+ "Count", "pFields" })
+ public class PRINTER_NOTIFY_OPTIONS_TYPE extends Structure {
+
+ public static class ByReference extends PRINTER_NOTIFY_OPTIONS_TYPE
+ implements Structure.ByReference {
+ }
+
+ /**
+ * The type to be watched.
+ */
+ public short Type;
+
+ /**
+ * Reserved.
+ */
+ public short Reserved0;
+
+ /**
+ * Reserved.
+ */
+ public int Reserved1;
+
+ /**
+ * Reserved.
+ */
+ public int Reserved2;
+
+ /**
+ * The number of elements in the pFields array.
+ */
+ public int Count;
+
+ /**
+ * A pointer to an array of values. Each element of the array specifies
+ * a job or printer information field of interest.
+ */
+ public Pointer pFields;
+
+ public void setFields(short[] fields) {
+ final long shortSizeInBytes = 2L;
+ Memory fieldsMemory = new Memory(fields.length * shortSizeInBytes);
+ fieldsMemory.write(0, fields, 0, fields.length);
+ pFields = fieldsMemory;
+ Count = fields.length;
+ }
+
+ public short[] getFields() {
+ return pFields.getShortArray(0, Count);
+ }
+ }
+
+ /**
+ * The PRINTER_NOTIFY_INFO structure contains printer information returned
+ * by the FindNextPrinterChangeNotification function. The function returns
+ * this information after a wait operation on a printer change notification
+ * object has been satisfied.
+ *
+ * @see
+ *
+ * PRINTER_NOTIFY_INFO structure
+ *
+ */
+ @Structure.FieldOrder({ "Version", "Flags", "Count", "aData" })
+ public class PRINTER_NOTIFY_INFO extends Structure {
+
+ /**
+ * The version of this structure. Set this member to 2.
+ */
+ public int Version;
+
+ /**
+ * A bit flag that indicates the state of the notification structure. If
+ * the PRINTER_NOTIFY_INFO_DISCARDED bit is set, it indicates that some
+ * notifications had to be discarded.
+ */
+ public int Flags;
+
+ /**
+ * The number of PRINTER_NOTIFY_INFO_DATA elements in the aData array.
+ */
+ public int Count;
+
+ /**
+ * An array of PRINTER_NOTIFY_INFO_DATA structures. Each element of the
+ * array identifies a single job or printer information field, and
+ * provides the current data for that field.
+ */
+ public PRINTER_NOTIFY_INFO_DATA[] aData =
+ new PRINTER_NOTIFY_INFO_DATA[1];
+
+ @Override
+ public void read() {
+ int count = (Integer) readField("Count");
+ aData = new PRINTER_NOTIFY_INFO_DATA[count];
+ if (count == 0) {
+ Count = count;
+ Version = (Integer) readField("Version");
+ Flags = (Integer) readField("Flags");
+ } else {
+ super.read();
+ }
+ }
+
+ }
+
+ /**
+ * A struct containing non-numeric notification data - conditional content
+ * of a {@link NOTIFY_DATA} union.
+ */
+ @Structure.FieldOrder({ "cbBuf", "pBuf" })
+ public class NOTIFY_DATA_DATA extends Structure {
+
+ /**
+ * Indicates the size, in bytes, of the buffer pointed to by pBuf.
+ */
+ public int cbBuf;
+
+ /**
+ * Pointer to a buffer that contains the field's current data.
+ */
+ public Pointer pBuf;
+
+ }
+
+ /**
+ * A union of data information based on the Type and Field members of
+ * {@link PRINTER_NOTIFY_INFO_DATA}
+ */
+ public class NOTIFY_DATA extends Union {
+
+ /**
+ * Set if the notification data is numeric.
+ *
+ * An array of two DWORD values. For information fields that use only a
+ * single DWORD, the data is in adwData [0].
+ */
+ public int[] adwData = new int[2];
+
+ /**
+ * Set if the notification data is non-numeric.
+ */
+ public NOTIFY_DATA_DATA Data;
+
+ }
+
+ /**
+ * The PRINTER_NOTIFY_INFO_DATA structure identifies a job or printer
+ * information field and provides the current data for that field.
+ *
+ * @see
+ *
+ * PRINTER_NOTIFY_INFO_DATA structure
+ *
+ */
+ @Structure.FieldOrder({ "Type", "Field", "Reserved", "Id", "NotifyData" })
+ public class PRINTER_NOTIFY_INFO_DATA extends Structure {
+
+ /**
+ * Indicates the type of information provided.
+ */
+ public short Type;
+
+ /**
+ * Indicates the field that changed.
+ */
+ public short Field;
+
+ /**
+ * Reserved.
+ */
+ public int Reserved;
+
+ /**
+ * Indicates the job identifier if the Type member specifies
+ * JOB_NOTIFY_TYPE. If the Type member specifies PRINTER_NOTIFY_TYPE,
+ * this member is undefined.
+ */
+ public int Id;
+
+ /**
+ * A union of data information based on the Type and Field members.
+ */
+ public NOTIFY_DATA NotifyData;
+
+ @Override
+ public void read() {
+ super.read();
+
+ boolean numericData;
+ if (Type == PRINTER_NOTIFY_TYPE) {
+ switch (Field) {
+ case PRINTER_NOTIFY_FIELD_ATTRIBUTES:
+ // Fall-through
+ case PRINTER_NOTIFY_FIELD_PRIORITY:
+ // Fall-through
+ case PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY:
+ // Fall-through
+ case PRINTER_NOTIFY_FIELD_START_TIME:
+ // Fall-through
+ case PRINTER_NOTIFY_FIELD_UNTIL_TIME:
+ // Fall-through
+ case PRINTER_NOTIFY_FIELD_STATUS:
+ // Fall-through
+ case PRINTER_NOTIFY_FIELD_CJOBS:
+ // Fall-through
+ case PRINTER_NOTIFY_FIELD_AVERAGE_PPM:
+ numericData = true;
+ default:
+ numericData = false;
+ }
+ } else {
+ switch (Field) {
+ case JOB_NOTIFY_FIELD_STATUS:
+ // Fall-through
+ case JOB_NOTIFY_FIELD_PRIORITY:
+ // Fall-through
+ case JOB_NOTIFY_FIELD_POSITION:
+ // Fall-through
+ case JOB_NOTIFY_FIELD_START_TIME:
+ // Fall-through
+ case JOB_NOTIFY_FIELD_UNTIL_TIME:
+ // Fall-through
+ case JOB_NOTIFY_FIELD_TIME:
+ // Fall-through
+ case JOB_NOTIFY_FIELD_TOTAL_PAGES:
+ // Fall-through
+ case JOB_NOTIFY_FIELD_PAGES_PRINTED:
+ // Fall-through
+ case JOB_NOTIFY_FIELD_TOTAL_BYTES:
+ // Fall-through
+ case JOB_NOTIFY_FIELD_BYTES_PRINTED:
+ numericData = true;
+ default:
+ numericData = false;
+ }
+ }
+ if (numericData) {
+ NotifyData.setType(int[].class);
+ } else {
+ NotifyData.setType(NOTIFY_DATA_DATA.class);
+ }
+ NotifyData.read();
+ }
+ }
+
+ @Deprecated
+ HANDLE FindFirstPrinterChangeNotification(
+ // _In_
+ HANDLE hPrinter,
+ int fdwFilter,
+ int fdwOptions,
+ // _In_opt_
+ LPVOID pPrinterNotifyOptions);
+
/**
* The FindFirstPrinterChangeNotification function creates a change
* notification object and returns a handle to the object. You can then use
@@ -614,9 +989,22 @@ boolean OpenPrinter(
*/
HANDLE FindFirstPrinterChangeNotification(
// _In_
- HANDLE hPrinter, int fdwFilter, int fdwOptions,
+ HANDLE hPrinter,
+ int fdwFilter,
+ int fdwOptions,
// _In_opt_
- LPVOID pPrinterNotifyOptions);
+ PRINTER_NOTIFY_OPTIONS pPrinterNotifyOptions);
+
+ @Deprecated
+ boolean FindNextPrinterChangeNotification(
+ // _In_
+ HANDLE hChange,
+ // _Out_opt_
+ DWORDByReference pdwChange,
+ // _In_opt_
+ LPVOID pPrinterNotifyOptions,
+ // _Out_opt_
+ LPVOID ppPrinterNotifyInfo);
/**
* The FindNextPrinterChangeNotification function retrieves information
@@ -689,9 +1077,9 @@ boolean FindNextPrinterChangeNotification(
// _Out_opt_
DWORDByReference pdwChange,
// _In_opt_
- LPVOID pPrinterNotifyOptions,
+ PRINTER_NOTIFY_OPTIONS pPrinterNotifyOptions,
// _Out_opt_
- LPVOID ppPrinterNotifyInfo);
+ PointerByReference ppPrinterNotifyInfo);
/**
* The FindClosePrinterChangeNotification function closes a change
@@ -716,6 +1104,27 @@ boolean FindClosePrinterChangeNotification(
// _In_
HANDLE hChange);
+ /**
+ * The FreePrinterNotifyInfo function frees a system-allocated buffer
+ * created by the FindNextPrinterChangeNotification function.
+ *
+ * @param pPrinterNotifyInfo
+ * [in] Pointer to a PRINTER_NOTIFY_INFO buffer returned from a
+ * call to the FindNextPrinterChangeNotification function.
+ * FreePrinterNotifyInfo deallocates this buffer.
+ *
+ * @return If the function succeeds, the return value is a nonzero value. If
+ * the function fails, the return value is zero.
+ *
+ * @see
+ *
+ * FreePrinterNotifyInfo function
+ *
+ */
+ boolean FreePrinterNotifyInfo(
+ // _In_
+ Pointer pPrinterNotifyInfo);
+
/**
* The EnumJobs function retrieves information about a specified set of
* print jobs for a specified printer.
diff --git a/contrib/w32printing/build.xml b/contrib/w32printing/build.xml
index 296d8ca227..5ac1fca8a8 100644
--- a/contrib/w32printing/build.xml
+++ b/contrib/w32printing/build.xml
@@ -9,7 +9,7 @@
-
+
diff --git a/contrib/w32printing/src/com/sun/jna/platform/win32/Win32SpoolMonitor.java b/contrib/w32printing/src/com/sun/jna/platform/win32/Win32SpoolMonitor.java
index 8a006746d1..5cc6217a46 100644
--- a/contrib/w32printing/src/com/sun/jna/platform/win32/Win32SpoolMonitor.java
+++ b/contrib/w32printing/src/com/sun/jna/platform/win32/Win32SpoolMonitor.java
@@ -22,27 +22,38 @@
*/
package com.sun.jna.platform.win32;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
import java.text.DateFormat;
+import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinBase.FILETIME;
import com.sun.jna.platform.win32.WinBase.SYSTEMTIME;
import com.sun.jna.platform.win32.WinDef.DWORDByReference;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.HANDLEByReference;
-import com.sun.jna.platform.win32.Winspool.JOB_INFO_1;
+import com.sun.jna.platform.win32.Winspool.*;
+import com.sun.jna.ptr.PointerByReference;
+
+import static com.sun.jna.platform.win32.Winspool.*;
public class Win32SpoolMonitor {
- public Win32SpoolMonitor() {
+ private static final int TWO_DIMENSIONAL_PRINTERS = 0;
+
+ private static final Charset UTF_16LE = Charset.forName("UTF-16LE");
- String pPrinterName = "HP Color LaserJet CM4730 MFP PCL 6";
+ public void monitorPrinter(String pPrinterName) {
HANDLEByReference phPrinter = new HANDLEByReference();
Winspool.INSTANCE.OpenPrinter(pPrinterName, phPrinter, null);
// Get change notification handle for the printer
- HANDLE chgObject = Winspool.INSTANCE
- .FindFirstPrinterChangeNotification(phPrinter.getValue(),
- Winspool.PRINTER_CHANGE_JOB, 0, null);
+ HANDLE chgObject = Winspool.INSTANCE.FindFirstPrinterChangeNotification(
+ phPrinter.getValue(),
+ Winspool.PRINTER_CHANGE_JOB,
+ 0,
+ (PRINTER_NOTIFY_OPTIONS) null);
if (chgObject != null) {
while (true) {
@@ -51,9 +62,12 @@ public Win32SpoolMonitor() {
WinBase.INFINITE);
DWORDByReference pdwChange = new DWORDByReference();
- boolean fcnreturn = Winspool.INSTANCE
- .FindNextPrinterChangeNotification(chgObject,
- pdwChange, null, null);
+ boolean fcnreturn =
+ Winspool.INSTANCE.FindNextPrinterChangeNotification(
+ chgObject,
+ pdwChange,
+ (PRINTER_NOTIFY_OPTIONS) null,
+ (PointerByReference) null);
if (fcnreturn) {
JOB_INFO_1[] jobInfo1 = WinspoolUtil.getJobInfo1(phPrinter);
@@ -80,6 +94,120 @@ public int getLastError() {
return rc;
}
+ public void monitorAllPrinters() {
+ System.out.println("Monitoring all printers, press Ctrl + C to stop");
+ HANDLEByReference printServerHandle = new HANDLEByReference();
+ boolean success =
+ Winspool.INSTANCE.OpenPrinter(null, printServerHandle, null);
+ if (!success) {
+ int errorCode = Kernel32.INSTANCE.GetLastError();
+ throw new RuntimeException("Failed to access the print server - " +
+ errorCode);
+ }
+
+ try {
+ PRINTER_NOTIFY_OPTIONS options = new PRINTER_NOTIFY_OPTIONS();
+ options.Count = 1;
+ PRINTER_NOTIFY_OPTIONS_TYPE.ByReference optionsType =
+ new PRINTER_NOTIFY_OPTIONS_TYPE.ByReference();
+ optionsType.Type = JOB_NOTIFY_TYPE;
+ optionsType.setFields(new short[] {
+ JOB_NOTIFY_FIELD_PRINTER_NAME,
+ JOB_NOTIFY_FIELD_STATUS,
+ JOB_NOTIFY_FIELD_DOCUMENT
+ });
+ optionsType.toArray(1);
+ options.pTypes = optionsType;
+ HANDLE changeNotificationsHandle =
+ Winspool.INSTANCE.FindFirstPrinterChangeNotification(
+ printServerHandle.getValue(),
+ PRINTER_CHANGE_ADD_JOB |
+ PRINTER_CHANGE_SET_JOB |
+ PRINTER_CHANGE_DELETE_JOB,
+ TWO_DIMENSIONAL_PRINTERS,
+ options);
+ if (!isValidHandle(changeNotificationsHandle)) {
+ int errorCode = Kernel32.INSTANCE.GetLastError();
+ throw new RuntimeException("Failed to get a change handle - " +
+ errorCode);
+ }
+
+ try {
+ while (true) {
+ Kernel32.INSTANCE.WaitForSingleObject(
+ changeNotificationsHandle,
+ WinBase.INFINITE);
+
+ DWORDByReference change =
+ new DWORDByReference();
+ PointerByReference infoPointer = new PointerByReference();
+ success =
+ Winspool.INSTANCE.FindNextPrinterChangeNotification(
+ changeNotificationsHandle,
+ change,
+ options,
+ infoPointer);
+ if (!success) {
+ int errorCode = Kernel32.INSTANCE.GetLastError();
+ throw new RuntimeException("Failed to get printer " +
+ "change notification - " + errorCode);
+ }
+
+ System.out.println("Change - " +
+ String.format("0x%08X", change.getValue().longValue()));
+
+ if (infoPointer.getValue() != null) {
+ PRINTER_NOTIFY_INFO info =
+ Structure.newInstance(PRINTER_NOTIFY_INFO.class,
+ infoPointer.getValue());
+ info.read();
+
+ try {
+ if ((info.Flags & PRINTER_NOTIFY_INFO_DISCARDED) > 0) {
+ System.out.println("Some information was " +
+ "discarded");
+ }
+
+ for (PRINTER_NOTIFY_INFO_DATA data : info.aData) {
+ System.out.println("Job ID - " + data.Id);
+ if (data.Field == JOB_NOTIFY_FIELD_PRINTER_NAME) {
+ String printerName = new String(
+ data.NotifyData.Data.pBuf.getByteArray(
+ 0,
+ data.NotifyData.Data.cbBuf),
+ UTF_16LE);
+ System.out.println("Printer - " + printerName);
+ } else if (data.Field == JOB_NOTIFY_FIELD_STATUS) {
+ System.out.println("Status - " +
+ String.format("0x%08X", data.NotifyData.adwData[0]));
+ } else {
+ String jobName = new String(
+ data.NotifyData.Data.pBuf.getByteArray(
+ 0,
+ data.NotifyData.Data.cbBuf),
+ UTF_16LE);
+ System.out.println("Job Name - " + jobName);
+ }
+ }
+ } finally {
+ Winspool.INSTANCE.FreePrinterNotifyInfo(info.getPointer());
+ }
+ }
+ System.out.println("==================================================");
+ }
+ } finally {
+ Winspool.INSTANCE.FindClosePrinterChangeNotification(
+ changeNotificationsHandle);
+ }
+ } finally {
+ Winspool.INSTANCE.ClosePrinter(printServerHandle.getValue());
+ }
+ }
+
+ private boolean isValidHandle(HANDLE handle) {
+ return handle != null && !handle.equals(Kernel32.INVALID_HANDLE_VALUE);
+ }
+
private void printJobInfo(JOB_INFO_1 jobInfo1) {
FILETIME lpFileTime = new FILETIME();
Kernel32.INSTANCE.SystemTimeToFileTime(jobInfo1.Submitted, lpFileTime);
@@ -102,7 +230,17 @@ private void printJobInfo(JOB_INFO_1 jobInfo1) {
/**
* @param args
*/
- public static void main(String[] args) {
- new Win32SpoolMonitor();
+ public static void main(String[] args) throws Exception {
+ System.out.print("Please enter the name of a printer to monitor, " +
+ "or press enter to monitor all printers: ");
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(System.in));
+ String printer = reader.readLine();
+ Win32SpoolMonitor monitor = new Win32SpoolMonitor();
+ if (printer.isEmpty()) {
+ monitor.monitorAllPrinters();
+ } else {
+ monitor.monitorPrinter(printer);
+ }
}
}