java-native-access/jna · error · Win32Exception

Win32Exception (error code from GetLastError after EnumPrint

Error message

Win32Exception (error code from GetLastError after EnumPrinters)

What it means

WinspoolUtil.getPrinterInfo1() throws Win32Exception when the second (buffered) EnumPrinters call — with level 1 and PRINTER_ENUM_LOCAL — returns false. The exception is constructed from Kernel32.INSTANCE.GetLastError() so its message is the real Win32 failure (e.g. ERROR_ACCESS_DENIED, RPC failures). EnumPrinters is called twice: first to learn the needed buffer size, then to fill it; only failures of the buffered call throw here.

Source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/WinspoolUtil.java:56

 *
 * @author dblock[at]dblock.org, Ivan Ridao Freitas, Padrus, Artem Vozhdayenko
 */
public abstract class WinspoolUtil {

    public static PRINTER_INFO_1[] getPrinterInfo1() {
        IntByReference pcbNeeded = new IntByReference();
        IntByReference pcReturned = new IntByReference();
        Winspool.INSTANCE.EnumPrinters(Winspool.PRINTER_ENUM_LOCAL, null, 1,
                null, 0, pcbNeeded, pcReturned);
        if (pcbNeeded.getValue() <= 0) {
            return new PRINTER_INFO_1[0];
        }

        PRINTER_INFO_1 pPrinterEnum = new PRINTER_INFO_1(pcbNeeded.getValue());
        if (!Winspool.INSTANCE.EnumPrinters(Winspool.PRINTER_ENUM_LOCAL, null,
                1, pPrinterEnum.getPointer(), pcbNeeded.getValue(), pcbNeeded,
                pcReturned)) {
            throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
        }

        pPrinterEnum.read();

        return (PRINTER_INFO_1[]) pPrinterEnum.toArray(pcReturned.getValue());
    }

    public static PRINTER_INFO_2[] getPrinterInfo2() {
        return getPrinterInfo2(Winspool.PRINTER_ENUM_LOCAL);
    }

    /**
     * Returns printers that are physically attached to the local machine as
     * well as remote printers to which it has a network connection.
     */
    public static PRINTER_INFO_2[] getAllPrinterInfo2() {
        // When Name is NULL, setting Flags to PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS
        // enumerates printers that are installed on the local machine.

View on GitHub (pinned to d036ad9781)

Solutions

  1. Verify the Windows Print Spooler service is running (sc query spooler; net start spooler)
  2. Check the exception's error code: ERROR_ACCESS_DENIED implies insufficient permissions — run as a user with printer access
  3. Confirm the process runs in an interactive user session (printer enumeration requires a loaded user profile in many configurations)
  4. Catch Win32Exception and treat 'no printers' as an empty result rather than a hard failure

Example fix

// before
PRINTER_INFO_1[] printers = WinspoolUtil.getPrinterInfo1();
// after
PRINTER_INFO_1[] printers;
try {
    printers = WinspoolUtil.getPrinterInfo1();
} catch (Win32Exception e) {
    printers = new PRINTER_INFO_1[0];
}
Defensive patterns

Strategy: try-catch

Validate before calling

// check spooler is reachable before calling
boolean spoolerUp = runsWinSpoolerService(); // e.g. sc query spooler equivalent

Try / catch

try {
    printers = WinspoolUtil.getPrinterInfo1();
} catch (Win32Exception e) {
    log.error("EnumPrinters failed: " + e.getMessage());
    printers = new PRINTER_INFO_1[0];
}

Prevention

When it happens

Trigger: Calling WinspoolUtil.getPrinterInfo1() when EnumPrinters(PRINTER_ENUM_LOCAL, null, 1, buffer, pcbNeeded, pcReturned) fails on the buffered call — spooler service (Spooler) not running, access denied, or no printers and the call returns an unexpected error.

Common situations: Running in a service/session where the print spooler is stopped or disabled; restricted service accounts without printer access; containers or minimal Windows installs with no print subsystem.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/3bf5d537fe5aa187. Report an issue: GitHub.