using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel.Design; using System.Linq; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using Vanara.Extensions; using Vanara.InteropServices; namespace Vanara.PInvoke { public static partial class WinSpool { /// The AbortPrinter function deletes a printer's spool file if the printer is configured for spooling. /// /// Handle to the printer from which the spool file is deleted. Use the OpenPrinter or AddPrinter function to retrieve /// a printer handle. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// If the printer is not configured for spooling, the AbortPrinter function has no effect. /// The sequence for a print job is as follows: /// /// /// To begin a print job, call StartDocPrinter. /// /// /// To begin each page, call StartPagePrinter. /// /// /// To write data to a page, call WritePrinter. /// /// /// To end each page, call EndPagePrinter. /// /// /// Repeat 2, 3, and 4 for as many pages as necessary. /// /// /// To end the print job, call EndDocPrinter. /// /// /// /// When a page in a spooled file exceeds approximately 350 MB, it can fail to print and not send an error message. For example, /// this can occur when printing large EMF files. The page size limit depends on many factors including the amount of virtual memory /// available, the amount of memory allocated by calling processes, and the amount of fragmentation in the process heap. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/abortprinter BOOL AbortPrinter( _In_ HANDLE hPrinter ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "b361fba5-e4e7-4c9e-ab32-b8ab88dcb1dc")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AbortPrinter(HPRINTER hPrinter); /// The AddForm function adds a form to the list of available forms that can be selected for the specified printer. /// /// A handle to the printer that supports printing with the specified form. Use the OpenPrinter or AddPrinter function /// to retrieve a printer handle. /// /// The level of the structure to which pForm points. This value must be 1 or 2. /// A pointer to a FORM_INFO_1 or FORM_INFO_2 structure. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// An application can determine which forms are available for a printer by calling the EnumForms function. /// /// If pForm points to a FORM_INFO_2, then AddForm will fail if either a form with the specified name already exists /// or the structure's pKeyword value already exists. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/addform BOOL AddForm( _In_ HANDLE hPrinter, _In_ DWORD Level, _In_ // LPBYTE pForm ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "17b59019-f93a-4b57-86fb-91c61aecbac4")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddForm(HPRINTER hPrinter, uint Level, IntPtr pForm); /// The AddForm function adds a form to the list of available forms that can be selected for the specified printer. /// The type of the structure used in . /// /// A handle to the printer that supports printing with the specified form. Use the OpenPrinter or AddPrinter function /// to retrieve a printer handle. /// /// A FORM_INFO_1 or FORM_INFO_2 structure. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// An application can determine which forms are available for a printer by calling the EnumForms function. /// /// If pForm points to a FORM_INFO_2, then AddForm will fail if either a form with the specified name already exists /// or the structure's pKeyword value already exists. /// /// [PInvokeData("winspool.h", MSDNShortId = "17b59019-f93a-4b57-86fb-91c61aecbac4")] public static bool AddForm(HPRINTER hPrinter, in T pForm) where T : struct { if (!TryGetLevel("FORM_INFO_", out var lvl)) throw new ArgumentException($"{nameof(AddForm)} cannot process a structure of type {typeof(T).Name}."); using var mem = SafeCoTaskMemHandle.CreateFromStructure(pForm); return AddForm(hPrinter, lvl, mem); } /// /// The AddJob function adds a print job to the list of print jobs that can be scheduled by the print spooler. The function /// retrieves the name of the file you can use to store the job. /// /// /// A handle that specifies the printer for the print job. This must be a local printer that is configured as a spooled printer. If /// hPrinter is a handle to a remote printer connection, or if the printer is configured for direct printing, the AddJob /// function fails. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// /// The version of the print job information data structure that the function stores into the buffer pointed to by pData. Set this /// parameter to one. /// /// A pointer to a buffer that receives an data structure and a path string. /// /// The size, in bytes, of the buffer pointed to by pData. The buffer needs to be large enough to contain an ADDJOB_INFO_1 /// structure and a path string. /// /// /// A pointer to a variable that receives the total size, in bytes, of the data structure plus the path /// string. If this value is less than or equal to cbBuf and the function succeeds, this is the actual number of bytes written to /// the buffer pointed to by pData. If this number is greater than cbBuf, the buffer is too small, and you must call the function /// again with a buffer size at least as large as *pcbNeeded. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// You can call the CreateFile function to open the spool file specified by the Path member of the /// ADDJOB_INFO_1 structure, and then call the WriteFile function to write print job data to it. After that is done, /// call the ScheduleJob function to notify the print spooler that the print job can now be scheduled by the spooler for printing. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/addjob BOOL AddJob( _In_ HANDLE hPrinter, _In_ DWORD Level, _Out_ LPBYTE // pData, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "cfafa874-6022-4bf4-bf3d-096213eb0c98")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddJob(HPRINTER hPrinter, uint Level, IntPtr pData, uint cbBuf, out uint pcbNeeded); /// /// The AddJob function adds a print job to the list of print jobs that can be scheduled by the print spooler. The function /// retrieves the name of the file you can use to store the job. /// /// /// A handle that specifies the printer for the print job. This must be a local printer that is configured as a spooled printer. If /// hPrinter is a handle to a remote printer connection, or if the printer is configured for direct printing, the AddJob /// function fails. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// The path and file name that the application can use to store the print job. /// A handle to the print job. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// You can call the CreateFile function to open the spool file specified by , and then call the /// WriteFile function to write print job data to it. After that is done, call the ScheduleJob function to notify the /// print spooler that the print job can now be scheduled by the spooler for printing. /// [PInvokeData("winspool.h", MSDNShortId = "cfafa874-6022-4bf4-bf3d-096213eb0c98")] public static bool AddJob(HPRINTER hPrinter, out string path, out uint jobId) { path = null; jobId = 0; AddJob(hPrinter, 1, default, 0, out var sz); if (sz == 0) return false; using var mem = new SafeCoTaskMemHandle(sz); if (!AddJob(hPrinter, 1, mem, sz, out sz)) return false; var str = mem.ToStructure(); path = str.Path; jobId = str.JobId; return true; } /// The AddPrinter function adds a printer to the list of supported printers for a specified server. /// /// A pointer to a null-terminated string that specifies the name of the server on which the printer should be installed. If this /// string is NULL, the printer is installed locally. /// /// The version of the structure to which pPrinter points. This value must be 2. /// /// A pointer to a PRINTER_INFO_2 structure that contains information about the printer. You must specify non- NULL /// values for the pPrinterName, pPortName, pDriverName, and pPrintProcessor members of this structure /// before calling AddPrinter. /// /// /// /// If the function succeeds, the return value is a handle (not thread safe) to a new printer object. When you are finished with the /// handle, pass it to the ClosePrinter function to close it. /// /// If the function fails, the return value is NULL. /// /// /// Do not call this method in DllMain. /// The caller must have the SeLoadDriverPrivilege. /// /// The returned handle is not thread safe. If callers need to use it concurrently on multiple threads, they must provide custom /// synchronization access to the printer handle using the Synchronization Functions. To avoid writing custom code the application /// can open a printer handle on each thread, as needed. /// /// /// The following are the members of the PRINTER_INFO_2 structure that can be set before the AddPrinter function is called: /// /// /// /// Attributes /// /// /// pPrintProcessor /// /// /// DefaultPriority /// /// /// Priority /// /// /// pComment /// /// /// pSecurityDescriptor /// /// /// pDatatype /// /// /// pSepFile /// /// /// pDevMode /// /// /// pShareName /// /// /// pLocation /// /// /// StartTime /// /// /// pParameters /// /// /// UntilTime /// /// /// /// The Status, cJobs, and AveragePPM members of the PRINTER_INFO_2 structure are reserved for use by /// the GetPrinter function. They must not be set before calling AddPrinter. /// /// /// If pSecurityDescriptor is NULL, the system assigns a default security descriptor to the printer. The default /// security descriptor has the following permissions. /// /// /// /// Value /// Description /// /// /// Administrators and Power Users /// /// Full control on the print queue. This means members of these groups can print, manage the queue (can delete the queue, change /// any setting of the queue, including the security descriptor), and manage the print jobs of all users (delete, pause, resume, /// restart jobs).Note that Power Users do not exist before Windows XP Professional. /// /// /// /// Creator/Owner /// Can manage own jobs. This means that user who submit jobs can manage (delete, pause, resume, restart) their own jobs. /// /// /// Everyone /// /// Execute and standard read control. This means that members of the everyone group can print and read properties of the print queue. /// /// /// /// /// After an application creates a printer object with the AddPrinter function, it must use the PrinterProperties /// function to specify the correct settings for the printer driver associated with the printer object. /// /// /// The AddPrinter function returns an error if a printer object with the same name already exists, unless that object is /// marked as pending deletion. In that case, the existing printer is not deleted, and the AddPrinter creation parameters are /// used to change the existing printer settings (as if the application had used the SetPrinter function). /// /// /// Use the EnumPrintProcessors function to enumerate the set of print processors installed on a server. Use the /// EnumPrintProcessorDatatypes function to enumerate the set of data types that a print processor supports. Use the /// EnumPorts function to enumerate the set of available ports. Use the EnumPrinterDrivers function to enumerate the /// installed printer drivers. /// /// /// The caller of the AddPrinter function must have SERVER_ACCESS_ADMINISTER access to the server on which the printer is to /// be created. The handle returned by the function will have PRINTER_ALL_ACCESS permission, and can be used to perform /// administrative operations on the printer. /// /// /// If the DrvPrinterEvent function is passed the PRINTER_EVENT_FLAG_NO_UI flag, the driver should not use a UI call during /// DrvPrinterEvent. To do UI-related jobs, the installer should either use the VendorSetup entry in the printer's /// .inf file or, for Plug and Play devices, the installer can use a device-specific co-installer. For more information about /// VendorSetup, see the Microsoft Windows Driver Development Kit (DDK). /// /// /// The Internet Connection Firewall (ICF) blocks printer ports by default, but an exception for File and Print Sharing is enabled /// when you run AddPrinter. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/addprinter HANDLE AddPrinter( _In_ LPTSTR *pName, _In_ DWORD Level, _In_ // LPBYTE pPrinter ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "ffc4fee8-46c6-47ad-803d-623bf8efdefd")] public static extern SafeHPRINTER AddPrinter([Optional] string pName, uint Level, in PRINTER_INFO_2 pPrinter); /// The AddPrinterConnection function adds a connection to the specified printer for the current user. /// /// A pointer to a null-terminated string that specifies the name of a printer to which the current user wishes to establish a connection. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// When Windows makes a connection to a printer, it may need to copy printer driver files to the server to which the printer is /// attached. If the user does not have permission to copy files to the appropriate location, the AddPrinterConnection /// function fails, and GetLastError returns ERROR_ACCESS_DENIED. /// /// /// A printer connection established by calling AddPrinterConnection will be enumerated when EnumPrinters is called /// with dwType set to PRINTER_ENUM_CONNECTION. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/addprinterconnection BOOL AddPrinterConnection( _In_ LPTSTR pName ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "6decf89a-1411-4e7e-aa20-60e7068658c2")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddPrinterConnection(string pName); /// Adds a connection to the specified printer for the current user and specifies connection details. /// /// A handle to the parent window in which the dialog box will be displayed if the print system must download a printer driver from /// the print server for this connection. /// /// /// A pointer to a constant null-terminated string specifying the name of the printer to which the current user wishes to connect. /// /// /// The version of the structure pointed to by pConnectionInfo. Currently, only level 1 is defined so the value of dwLevel must be 1. /// /// /// A pointer to a structure. See the Remarks section for more about this parameter. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. For extended error information, call GetLastError. /// /// /// /// When Windows Vista makes a connection to a printer, it may need to copy printer driver files from the server to which the /// printer is attached. If the user does not have permission to copy files to the appropriate location, the /// AddPrinterConnection2 function fails and GetLastError returns ERROR_ACCESS_DENIED. /// /// /// If the printer driver files must be copied from the print server but cannot be copied silently due to the group policies that /// are in effect and PRINTER_CONNECTION_NO_UI is set in pConnectionInfo->dwFlags, no dialog boxes will be displayed and the call /// will fail. /// /// /// If the local printer driver can be used to render print jobs for this printer and the version of the local driver must not match /// the version of the printer driver on the server, set PRINTER_CONNECTION_MISMATCH in pConnectionInfo->dwFlags and assign the /// pointer to a string variable that contains the path to the local printer driver to pConnectionInfo->pszDriverName. /// /// /// A printer connection that is established by calling AddPrinterConnection2 will be enumerated when EnumPrinters is /// called with dwType set to PRINTER_ENUM_CONNECTION. /// /// The ANSI version of this function, AddPrinterConnection2A, is not supported and returns ERROR_NOT_SUPPORTED. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/addprinterconnection2 BOOL AddPrinterConnection2( _In_ HWND hWnd, _In_ // LPCTSTR pszName, DWORD dwLevel, _In_ PVOID pConnectionInfo ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Unicode)] [PInvokeData("winspool.h", MSDNShortId = "5ae98157-5978-449e-beb1-4787110925fa")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddPrinterConnection2([Optional] HWND hWnd, string pszName, uint dwLevel, IntPtr pConnectionInfo); /// /// Adds a connection to the specified printer for the current user and specifies connection details. /// /// A handle to the parent window in which the dialog box will be displayed if the print system must download a printer driver from /// the print server for this connection. /// A pointer to a constant null-terminated string specifying the name of the printer to which the current user wishes to connect. /// /// The following values are defined: /// /// /// Value /// Meaning /// /// /// PRINTER_CONNECTION_MISMATCH (0x00000020) /// /// If this bit-flag is set, the printer connection is mismatched. The user can supply a local print driver as pszDriverName and /// use it to do the rendering instead of using the driver installed on the server printer to which the user is connected. /// /// /// /// PRINTER_CONNECTION_NO_UI (0x00000040) /// /// If this bit-flag is set then this call cannot display a dialog box. If a dialog box must be displayed to install a printer /// driver from the server and this bit-flag is set, the printer driver will not be installed, the printer connection will not /// be added, and the call will fail. Windows 7: In Windows 7 and later versions of Windows, if this flag is set and the user is /// running in elevated mode, the Do you trust this printer? dialog will not be shown. /// /// /// /// /// The name of the driver. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. For extended error information, call GetLastError. /// /// /// /// When Windows Vista makes a connection to a printer, it may need to copy printer driver files from the server to which the /// printer is attached. If the user does not have permission to copy files to the appropriate location, the /// AddPrinterConnection2 function fails and GetLastError returns ERROR_ACCESS_DENIED. /// /// /// If the printer driver files must be copied from the print server but cannot be copied silently due to the group policies that /// are in effect and PRINTER_CONNECTION_NO_UI is set in , no dialog boxes will be displayed and the call /// will fail. /// /// /// If the local printer driver can be used to render print jobs for this printer and the version of the local driver must not match /// the version of the printer driver on the server, set PRINTER_CONNECTION_MISMATCH in and assign the /// string variable that contains the path to the local printer driver to . /// /// /// A printer connection that is established by calling AddPrinterConnection2 will be enumerated when EnumPrinters is /// called with dwType set to PRINTER_ENUM_CONNECTION. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/addprinterconnection2 BOOL AddPrinterConnection2( _In_ HWND hWnd, _In_ // LPCTSTR pszName, DWORD dwLevel, _In_ PVOID pConnectionInfo ); [PInvokeData("winspool.h", MSDNShortId = "5ae98157-5978-449e-beb1-4787110925fa")] public static bool AddPrinterConnection2([Optional] HWND hWnd, string pszName, PRINTER_CONNECTION_FLAGS flags, string driverName = null) => AddPrinterConnection2(hWnd, pszName, 1, new PRINTER_CONNECTION_INFO_1 { dwFlags = flags, pszDriverName = driverName }); /// /// /// The AdvancedDocumentProperties function displays a printer-configuration dialog box for the specified printer, allowing /// the user to configure that printer. /// /// This function is a special case of the DocumentProperties function. For more details, see the Remarks section. /// /// A handle to the parent window of the printer-configuration dialog box. /// /// A handle to a printer object. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// /// A pointer to a null-terminated string specifying the name of the device for which a printer-configuration dialog box should be displayed. /// /// /// A pointer to a DEVMODE structure that will contain the configuration data specified by the user. /// /// /// A pointer to a DEVMODE structure that contains the configuration data used to initialize the controls of the /// printer-configuration dialog box. /// /// /// If the DocumentProperties function with these parameters is successful, the return value of /// AdvancedDocumentProperties is 1. Otherwise, the return value is zero. /// /// /// /// This function can only display the printer-configuration dialog box so a user can configure it. For more control, use /// DocumentProperties. The input parameters for this function are passed directly to DocumentProperties and the fMode /// value is set to DM_IN_BUFFER | DM_IN_PROMPT | DM_OUT_BUFFER. Unlike DocumentProperties, this function only returns 1 or /// 0. Thus, you cannot determine the required size of DEVMODE by setting pDevMode to zero. /// /// /// An application can obtain the name pointed to by the pDeviceName parameter by calling the GetPrinter function and then /// examining the pPrinterName member of the PRINTER_INFO_2 structure. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/advanceddocumentproperties LONG AdvancedDocumentProperties( _In_ HWND // hWnd, _In_ HANDLE hPrinter, _In_ LPTSTR pDeviceName, _Out_ PDEVMODE pDevModeOutput, _In_ PDEVMODE pDevModeInput ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "29e33f34-f6ec-4989-b076-e1fef8eb5bc4")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AdvancedDocumentProperties(HWND hWnd, HPRINTER hPrinter, string pDeviceName, ref DEVMODE pDevModeOutput, in DEVMODE pDevModeInput); /// /// /// The AdvancedDocumentProperties function displays a printer-configuration dialog box for the specified printer, allowing /// the user to configure that printer. /// /// This function is a special case of the DocumentProperties function. For more details, see the Remarks section. /// /// A handle to the parent window of the printer-configuration dialog box. /// /// A handle to a printer object. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// /// A pointer to a null-terminated string specifying the name of the device for which a printer-configuration dialog box should be displayed. /// /// /// A pointer to a DEVMODE structure that will contain the configuration data specified by the user. /// /// /// A pointer to a DEVMODE structure that contains the configuration data used to initialize the controls of the /// printer-configuration dialog box. /// /// /// If the DocumentProperties function with these parameters is successful, the return value of /// AdvancedDocumentProperties is 1. Otherwise, the return value is zero. /// /// /// /// This function can only display the printer-configuration dialog box so a user can configure it. For more control, use /// DocumentProperties. The input parameters for this function are passed directly to DocumentProperties and the fMode /// value is set to DM_IN_BUFFER | DM_IN_PROMPT | DM_OUT_BUFFER. Unlike DocumentProperties, this function only returns 1 or /// 0. Thus, you cannot determine the required size of DEVMODE by setting pDevMode to zero. /// /// /// An application can obtain the name pointed to by the pDeviceName parameter by calling the GetPrinter function and then /// examining the pPrinterName member of the PRINTER_INFO_2 structure. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/advanceddocumentproperties LONG AdvancedDocumentProperties( _In_ HWND // hWnd, _In_ HANDLE hPrinter, _In_ LPTSTR pDeviceName, _Out_ PDEVMODE pDevModeOutput, _In_ PDEVMODE pDevModeInput ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "29e33f34-f6ec-4989-b076-e1fef8eb5bc4")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AdvancedDocumentProperties(HWND hWnd, HPRINTER hPrinter, string pDeviceName, [Out] IntPtr pDevModeOutput = default, [In] IntPtr pDevModeInput = default); /// The ClosePrinter function closes the specified printer object. /// /// A handle to the printer object to be closed. This handle is returned by the OpenPrinter or AddPrinter function. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// When the ClosePrinter function returns, the handle hPrinter is invalid, regardless of whether the function has succeeded /// or failed. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/closeprinter BOOL ClosePrinter( _In_ HANDLE hPrinter ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "95cc3eca-e65c-4fa6-8975-479e8e728dca")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ClosePrinter(HPRINTER hPrinter); /// /// The CloseSpoolFileHandle function closes a handle to a spool file associated with the print job currently submitted by /// the application. /// /// /// A handle to the printer to which the job was submitted. This should be the same handle that was used to obtain hSpoolFile with GetSpoolFileHandle. /// /// /// A handle to the spool file being closed. If CommitSpoolData has not been called since GetSpoolFileHandle was /// called, then this should be the same handle that was returned by GetSpoolFileHandle. Otherwise, it should be the handle /// that was returned by the most recent call to CommitSpoolData. /// /// TRUE, if it succeeds, FALSE otherwise. /// /// Your application must not call ClosePrinter on hPrinter until after it has accessed the spool file for the last time. /// Then it should call CloseSpoolFileHandle followed by ClosePrinter. Attempts to access the spool file handle after /// the original hPrinter has been closed will fail even if the file handle itself has not been closed. CloseSpoolFileHandle /// will fail if ClosePrinter is called first. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/closespoolfilehandle BOOL CloseSpoolFileHandle( _In_ HANDLE hPrinter, // _In_ HANDLE hSpoolFile ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "e2c0e68f-b72e-4a97-ba18-8943bc5789c1")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CloseSpoolFileHandle(HPRINTER hPrinter, HSPOOLFILE hSpoolFile); /// /// The CommitSpoolData function notifies the print spooler that a specified amount of data has been written to a specified /// spool file and is ready to be rendered. /// /// /// A handle to the printer to which the job was submitted. This should be the same handle that was used to obtain hSpoolFile with GetSpoolFileHandle. /// /// /// A handle to the spool file being changed. On the first call of CommitSpoolData, this should be the same handle that was /// returned by GetSpoolFileHandle. Subsequent calls to CommitSpoolData should pass the handle returned by the /// preceding call. See Remarks. /// /// The number of bytes committed to the print spooler. /// /// If the function succeeds, it returns a handle to the spool file. /// If the function fails, it returns INVALID_HANDLE_VALUE. /// /// /// /// Applications submitting a spooler print job can call GetSpoolFileHandle and then directly write data to the spool file /// handle by calling WriteFile. To notify the print spooler that the file contains data which is ready to be rendered, the /// application must call CommitSpoolData and provide the number of available bytes. /// /// /// If CommitSpoolData is called multiple times, each call must use the spool file handle returned by the previous call. When /// no more data will be written to the spool file, CloseSpoolFileHandle should be called for the file handle returned by the /// last call to CommitSpoolData. /// /// /// Before calling CommitSpoolData, applications must set the file pointer to the position it had before it wrote data to the /// file. In the process of rendering the data in the spooler file, the print spooler will move the spool file pointer cbCommit /// bytes from the current value of file pointer. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/commitspooldata HANDLE CommitSpoolData( _In_ HANDLE hPrinter, _In_ // HANDLE hSpoolFile, DWORD cbCommit ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "cb8899e0-2fdf-4928-adff-17ef5af39f63")] public static extern HANDLE CommitSpoolData(HPRINTER hPrinter, HSPOOLFILE hSpoolFile, uint cbCommit); /// The ConfigurePort function displays the port-configuration dialog box for a port on the specified server. /// /// Pointer to a null-terminated string that specifies the name of the server on which the specified port exists. If this parameter /// is NULL, the port is local. /// /// Handle to the parent window of the port-configuration dialog box. /// Pointer to a null-terminated string that specifies the name of the port to be configured. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// Before calling the ConfigurePort function, an application should call the EnumPorts function to determine valid /// port names. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/configureport BOOL ConfigurePort( _In_ LPTSTR pName, _In_ HWND hWnd, // _In_ LPTSTR pPortName ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "a65e9876-d6af-48c2-9e6b-8bd8695db130")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ConfigurePort([Optional] string pName, HWND hWnd, string pPortName); /// /// The ConnectToPrinterDlg function displays a dialog box that lets users browse and connect to printers on a network. If /// the user selects a printer, the function attempts to create a connection to it; if a suitable driver is not installed on the /// server, the user is given the option of creating a printer locally. /// /// Specifies the parent window of the dialog box. /// This parameter is reserved and must be zero. /// /// If the function succeeds and the user selects a printer, the return value is a handle to the selected printer. /// If the function fails, or the user cancels the dialog box without selecting a printer, the return value is NULL. /// /// /// /// The ConnectToPrinterDlg function attempts to create a connection to the selected printer. However, if the server on which /// the printer resides does not have a suitable driver installed, the function offers the user the option of creating a printer /// locally. A calling application can determine whether the function has created a printer locally by calling GetPrinter /// with a PRINTER_INFO_2 structure, then examining that structure's Attributes member. /// /// /// An application should call DeletePrinter to delete a local printer. An application should call /// DeletePrinterConnection to delete a connection to a printer. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/connecttoprinterdlg HANDLE ConnectToPrinterDlg( _In_ HWND hwnd, _In_ // DWORD Flags ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "7cb9108b-8b65-4af3-88c8-a69771ed8e3f")] public static extern SafeHPRINTER ConnectToPrinterDlg(HWND hwnd, uint Flags = 0); /// The DeleteForm function removes a form name from the list of supported forms. /// /// Indicates the open printer handle that this function is to be performed upon. Use the OpenPrinter or AddPrinter /// function to retrieve a printer handle. /// /// Pointer to the form name to be removed. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// DeleteForm can only delete form names that were added by using the AddForm function. // https://docs.microsoft.com/en-us/windows/win32/printdocs/deleteform BOOL DeleteForm( _In_ HANDLE hPrinter, _In_ LPTSTR pFormName ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "a2d0345f-2469-46ab-935f-777f2b33b621")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DeleteForm(HPRINTER hPrinter, string pFormName); /// The DeletePrinter function deletes the specified printer object. /// /// Handle to a printer object that will be deleted. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// If there are print jobs remaining to be processed for the specified printer, DeletePrinter marks the printer for pending /// deletion, and then deletes it when all the print jobs have been printed. No print jobs can be added to a printer that is marked /// for pending deletion. /// /// /// A printer marked for pending deletion cannot be held, but its print jobs can be held, resumed, and restarted. If the printer is /// held and there are jobs for the printer, DeletePrinter fails with ERROR_ACCESS_DENIED. /// /// Note that DeletePrinter does not close the handle that is passed to it. Thus, the application must still call ClosePrinter. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/deleteprinter BOOL DeletePrinter( _Inout_ HANDLE hPrinter ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "04d9c073-b795-4307-ba89-d4984bc5b354")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DeletePrinter(HPRINTER hPrinter); /// /// The DeletePrinterConnection function deletes a connection to a printer that was established by a call to /// AddPrinterConnection or ConnectToPrinterDlg. /// /// Pointer to a null-terminated string that specifies the name of the printer connection to delete. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// The DeletePrinterConnection function does not delete any printer driver files that were copied to the server to which the /// printer is attached. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/deleteprinterconnection BOOL DeletePrinterConnection( _In_ LPTSTR pName ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "7b056eea-fbd9-4a08-a2dc-7326caeec387")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DeletePrinterConnection(string pName); /// /// /// The DeletePrinterData function deletes specified configuration data for a printer. A printer's configuration data /// consists of a set of named and typed values. The DeletePrinterData function deletes one of these values, specified by its /// value name. /// /// /// Calling DeletePrinterData is equivalent to calling the DeletePrinterDataEx function with the pKeyName parameter /// set to "PrinterDriverData". /// /// /// /// A handle to the printer whose configuration data is to be deleted. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// A pointer to the null-terminated name of the configuration data value to be deleted. /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is a system error code. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/deleteprinterdata DWORD DeletePrinterData( _In_ HANDLE hPrinter, _In_ // LPTSTR pValueName ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "03c0bd75-d6de-46e3-b8e9-5a55df5135ea")] public static extern Win32Error DeletePrinterData(HPRINTER hPrinter, string pValueName); /// /// /// The DeletePrinterDataEx function deletes a specified value from the configuration data for a printer. A printer's /// configuration data consists of a set of named and typed values stored in a hierarchy of registry keys. The function deletes a /// specified value under a specified key. /// /// /// Like the DeletePrinterData function, DeletePrinterDataEx can delete values stored by the SetPrinterData /// function. In addition, DeletePrinterDataEx can delete values stored under a specified key by the SetPrinterDataEx function. /// /// /// /// A handle to the printer for which the function deletes a value. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// /// /// A pointer to a null-terminated string that specifies the key containing the value to delete. Use the backslash ( \ ) character /// as a delimiter to specify a path that has one or more subkeys. /// /// If pKeyName is NULL or an empty string, DeletePrinterDataEx returns ERROR_INVALID_PARAMETER. /// /// A pointer to a null-terminated string that specifies the name of the value to delete. /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is a system error code. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/deleteprinterdataex DWORD DeletePrinterDataEx( _In_ HANDLE hPrinter, // _In_ LPCTSTR pKeyName, _In_ LPCTSTR pValueName ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "bcc9cdb3-0fbf-40b6-9de2-1479c3c0ff55")] public static extern Win32Error DeletePrinterDataEx(HPRINTER hPrinter, string pKeyName, string pValueName); /// The DeletePrinterKey function deletes a specified key and all its subkeys for a specified printer. /// /// A handle to the printer for which the function deletes a key. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// /// /// A pointer to a null-terminated string that specifies the key to delete. Use the backslash ( \ ) character as a delimiter to /// specify a path with one or more subkeys. /// /// /// If pKeyName is an empty string (""), DeletePrinterKey deletes all keys below the top-level key for the printer. If /// pKeyName is NULL, DeletePrinterKey returns ERROR_INVALID_PARAMETER. /// /// /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is a system error code. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/deleteprinterkey DWORD DeletePrinterKey( _In_ HANDLE hPrinter, _In_ // LPCTSTR pKeyName ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "0bd81b43-5c1e-4989-8350-2ec0dc215f28")] public static extern Win32Error DeletePrinterKey(HPRINTER hPrinter, string pKeyName); /// The DeviceCapabilities function retrieves the capabilities of a printer driver. /// /// A pointer to a null-terminated string that contains the name of the printer. Note that this is the name of the printer, not of /// the printer driver. /// /// /// A pointer to a null-terminated string that contains the name of the port to which the device is connected, such as LPT1. /// /// /// The capabilities to be queried. This parameter can be one of the following values. /// /// /// Value /// Meaning /// /// /// DC_BINNAMES /// /// Retrieves the names of the printer's paper bins. The pOutput buffer receives an array of string buffers. Each string buffer is /// 24 characters long and contains the name of a paper bin. The return value indicates the number of entries in the array. The name /// strings are null-terminated unless the name is 24 characters long. If pOutput is NULL, the return value is the number of bin /// entries required. /// /// /// /// DC_BINS /// /// Retrieves a list of available paper bins. The pOutput buffer receives an array of WORD values that indicate the available paper /// sources for the printer. The return value indicates the number of entries in the array. For a list of the possible array values, /// see the description of the dmDefaultSource member of the DEVMODE structure. If pOutput is NULL, the return value indicates the /// required number of entries in the array. /// /// /// /// DC_COLLATE /// /// If the printer supports collating, the return value is 1; otherwise, the return value is zero. The pOutput parameter is not used. /// /// /// /// DC_COLORDEVICE /// /// If the printer supports color printing, the return value is 1; otherwise, the return value is zero. The pOutput parameter is not used. /// /// /// /// DC_COPIES /// Returns the number of copies the device can print. /// /// /// DC_DRIVER /// Returns the version number of the printer driver. /// /// /// DC_DUPLEX /// /// If the printer supports duplex printing, the return value is 1; otherwise, the return value is zero. The pOutput parameter is /// not used. /// /// /// /// DC_ENUMRESOLUTIONS /// /// Retrieves a list of the resolutions supported by the printer. The pOutput buffer receives an array of LONG values. For each /// supported resolution, the array contains a pair of LONG values that specify the x and y dimensions of the resolution, in dots /// per inch. The return value indicates the number of supported resolutions. If pOutput is NULL, the return value indicates the /// number of supported resolutions. /// /// /// /// DC_EXTRA /// Returns the number of bytes required for the device-specific portion of the DEVMODE structure for the printer driver. /// /// /// DC_FIELDS /// /// Returns the dmFields member of the printer driver's DEVMODE structure. The dmFields member indicates which members in the /// device-independent portion of the structure are supported by the printer driver. /// /// /// /// DC_FILEDEPENDENCIES /// /// Retrieves the names of any additional files that need to be loaded when a driver is installed. The pOutput buffer receives an /// array of string buffers. Each string buffer is 64 characters long and contains the name of a file. The return value indicates /// the number of entries in the array. The name strings are null-terminated unless the name is 64 characters long. If pOutput is /// NULL, the return value is the number of files. /// /// /// /// DC_MAXEXTENT /// /// Returns the maximum paper size that the dmPaperLength and dmPaperWidth members of the printer driver's DEVMODE structure can /// specify. The LOWORD of the return value contains the maximum dmPaperWidth value, and the HIWORD contains the maximum /// dmPaperLength value. /// /// /// /// DC_MEDIAREADY /// /// Retrieves the names of the paper forms that are currently available for use. The pOutput buffer receives an array of string /// buffers. Each string buffer is 64 characters long and contains the name of a paper form. The return value indicates the number /// of entries in the array. The name strings are null-terminated unless the name is 64 characters long. If pOutput is NULL, the /// return value is the number of paper forms. /// /// /// /// DC_MEDIATYPENAMES /// /// Retrieves the names of the supported media types. The pOutput buffer receives an array of string buffers. Each string buffer is /// 64 characters long and contains the name of a supported media type. The return value indicates the number of entries in the /// array. The strings are null-terminated unless the name is 64 characters long. If pOutput is NULL, the return value is the number /// of media type names required. /// /// /// /// DC_MEDIATYPES /// /// Retrieves a list of supported media types. The pOutput buffer receives an array of DWORD values that indicate the supported /// media types. The return value indicates the number of entries in the array. For a list of possible array values, see the /// description of the dmMediaType member of the DEVMODE structure. If pOutput is NULL, the return value indicates the required /// number of entries in the array. /// /// /// /// DC_MINEXTENT /// /// Returns the minimum paper size that the dmPaperLength and dmPaperWidth members of the printer driver's DEVMODE structure can /// specify. The LOWORD of the return value contains the minimum dmPaperWidth value, and the HIWORD contains the minimum /// dmPaperLength value. /// /// /// /// DC_ORIENTATION /// /// Returns the relationship between portrait and landscape orientations for a device, in terms of the number of degrees that /// portrait orientation is rotated counterclockwise to produce landscape orientation. The return value can be one of the following: /// 0 No landscape orientation. 90 Portrait is rotated 90 degrees to produce landscape. 270 Portrait is rotated 270 degrees to /// produce landscape. /// /// /// /// DC_NUP /// /// Retrieves an array of integers that indicate that printer's ability to print multiple document pages per printed page. The /// pOutput buffer receives an array of DWORD values. Each value represents a supported number of document pages per printed page. /// The return value indicates the number of entries in the array. If pOutput is NULL, the return value indicates the required /// number of entries in the array. /// /// /// /// DC_PAPERNAMES /// /// Retrieves a list of supported paper names (for example, Letter or Legal). The pOutput buffer receives an array of string /// buffers. Each string buffer is 64 characters long and contains the name of a paper form. The return value indicates the number /// of entries in the array. The name strings are null-terminated unless the name is 64 characters long. If pOutput is NULL, the /// return value is the number of paper forms. /// /// /// /// DC_PAPERS /// /// Retrieves a list of supported paper sizes. The pOutput buffer receives an array of WORD values that indicate the available paper /// sizes for the printer. The return value indicates the number of entries in the array. For a list of the possible array values, /// see the description of the dmPaperSize member of the DEVMODE structure. If pOutput is NULL, the return value indicates the /// required number of entries in the array. /// /// /// /// DC_PAPERSIZE /// /// Retrieves the dimensions, in tenths of a millimeter, of each supported paper size. The pOutput buffer receives an array of POINT /// structures. Each structure contains the width (x-dimension) and length (y-dimension) of a paper size as if the paper were in the /// DMORIENT_PORTRAIT orientation. The return value indicates the number of entries in the array. /// /// /// /// DC_PERSONALITY /// /// Retrieves a list of printer description languages supported by the printer. The pOutput buffer receives an array of string /// buffers. Each buffer is 32 characters long and contains the name of a printer description language. The return value indicates /// the number of entries in the array. The name strings are null-terminated unless the name is 32 characters long. If pOutput is /// NULL, the return value indicates the required number of array entries. /// /// /// /// DC_PRINTERMEM /// The return value is the amount of available printer memory, in kilobytes. The pOutput parameter is not used. /// /// /// DC_PRINTRATE /// /// The return value indicates the printer's print rate. The value returned for DC_PRINTRATEUNIT indicates the units of the /// DC_PRINTRATE value. The pOutput parameter is not used. /// /// /// /// DC_PRINTRATEPPM /// The return value indicates the printer's print rate, in pages per minute. The pOutput parameter is not used. /// /// /// DC_PRINTRATEUNIT /// /// The return value is one of the following values that indicate the print rate units for the value returned for the DC_PRINTRATE /// flag. The pOutput parameter is not used. PRINTRATEUNIT_CPS Characters per second. PRINTRATEUNIT_IPM Inches per minute. /// PRINTRATEUNIT_LPM Lines per minute. PRINTRATEUNIT_PPM Pages per minute. /// /// /// /// DC_SIZE /// Returns the dmSize member of the printer driver's DEVMODE structure. /// /// /// DC_STAPLE /// /// If the printer supports stapling, the return value is a nonzero value; otherwise, the return value is zero. The pOutput /// parameter is not used. /// /// /// /// DC_TRUETYPE /// /// Retrieves the abilities of the driver to use TrueType fonts. For DC_TRUETYPE, the pOutput parameter should be NULL. The return /// value can be one or more of the following: DCTT_BITMAP Device can print TrueType fonts as graphics. DCTT_DOWNLOAD Device can /// download TrueType fonts. DCTT_SUBDEV Device can substitute device fonts for TrueType fonts. /// /// /// /// DC_VERSION /// Returns the specification version to which the printer driver conforms. /// /// /// /// /// A pointer to an array. The format of the array depends on the setting of the fwCapability parameter. See each capability above /// to find out what is returned if pOutput is NULL. /// /// /// A pointer to a DEVMODE structure. If this parameter is NULL, DeviceCapabilities retrieves the current default /// initialization values for the specified printer driver. Otherwise, the function retrieves the values contained in the structure /// to which pDevMode points. /// /// /// /// If the function succeeds, the return value depends on the setting of the fwCapability parameter. A return value of zero /// generally indicates that, while the function completed successfully, there was some type of failure, such as a capability that /// is not supported. For more details, see the descriptions for the fwCapability values. /// /// /// If the function returns -1, this may mean either that the capability is not supported or there was a general function failure. /// /// /// /// /// Note This is a blocking or synchronous function and might not return immediately. How quickly this function returns /// depends on run-time factors such as network status, print server configuration, and printer driver implementation—factors that /// are difficult to predict when writing an application. Calling this function from a thread that manages interaction with the user /// interface could make the application appear to be unresponsive. /// /// The DEVMODE structure pointed to by the pDevMode parameter may be obtained by calling the DocumentProperties function. /// /// If a printer driver supports custom device capabilities, the driver must call the SetPrinterData function for each custom /// capability. The SetPrinterData function adds the appropriate printer data to the print system, which enables 32-bit /// applications to access the custom capabilities on 64-bit Windows installations. /// /// /// For each custom capability, you must first add printer data that describes the type of the capability. To do this, when you call /// SetPrinterData, set the pValueName string to CustomDeviceCapabilityType_Xxx, where "Xxx" is the hexadecimal /// representation of the capability. For example, you might have "CustomDeviceCapabilityType_1234". The registry data that you set /// must be of the REG_DWORD type, and you must set its value to one of the following: /// /// /// /// 0, if the custom capability is a DWORD /// /// /// 1, if the custom capability is a buffer of bytes /// /// /// 2, if the custom capability is an array of items /// /// /// /// If the custom capability is an array of items, you must call SetPinterData a second time to provide information about the /// size of an item in the array. To do this, when you call SetPinterData, the pValueName string that you provide must be /// "CustomDeviceCapabilitySize_Xxx" where Xxx is the hexadecimal representation of the capability. For example, you might have /// "CustomDeviceCapabilitySize_1234". The registry data that you set must be of the REG_DWORD type, and you must set its /// value to the size in bytes of an item in the array. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-devicecapabilitiesa // int DeviceCapabilitiesA( LPCSTR pDevice, LPCSTR pPort, WORD fwCapability, LPSTR pOutput, const DEVMODEA *pDevMode ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("wingdi.h", MSDNShortId = "d7f63ef7-0a2e-47c3-9e81-6e8a6dffe9af")] public static extern int DeviceCapabilities(string pDevice, [Optional] string pPort, DC fwCapability, [Optional] IntPtr pOutput, in DEVMODE pDevMode); /// The DeviceCapabilities function retrieves the capabilities of a printer driver. /// /// A pointer to a null-terminated string that contains the name of the printer. Note that this is the name of the printer, not of /// the printer driver. /// /// /// A pointer to a null-terminated string that contains the name of the port to which the device is connected, such as LPT1. /// /// /// The capabilities to be queried. This parameter can be one of the following values. /// /// /// Value /// Meaning /// /// /// DC_BINNAMES /// /// Retrieves the names of the printer's paper bins. The pOutput buffer receives an array of string buffers. Each string buffer is /// 24 characters long and contains the name of a paper bin. The return value indicates the number of entries in the array. The name /// strings are null-terminated unless the name is 24 characters long. If pOutput is NULL, the return value is the number of bin /// entries required. /// /// /// /// DC_BINS /// /// Retrieves a list of available paper bins. The pOutput buffer receives an array of WORD values that indicate the available paper /// sources for the printer. The return value indicates the number of entries in the array. For a list of the possible array values, /// see the description of the dmDefaultSource member of the DEVMODE structure. If pOutput is NULL, the return value indicates the /// required number of entries in the array. /// /// /// /// DC_COLLATE /// /// If the printer supports collating, the return value is 1; otherwise, the return value is zero. The pOutput parameter is not used. /// /// /// /// DC_COLORDEVICE /// /// If the printer supports color printing, the return value is 1; otherwise, the return value is zero. The pOutput parameter is not used. /// /// /// /// DC_COPIES /// Returns the number of copies the device can print. /// /// /// DC_DRIVER /// Returns the version number of the printer driver. /// /// /// DC_DUPLEX /// /// If the printer supports duplex printing, the return value is 1; otherwise, the return value is zero. The pOutput parameter is /// not used. /// /// /// /// DC_ENUMRESOLUTIONS /// /// Retrieves a list of the resolutions supported by the printer. The pOutput buffer receives an array of LONG values. For each /// supported resolution, the array contains a pair of LONG values that specify the x and y dimensions of the resolution, in dots /// per inch. The return value indicates the number of supported resolutions. If pOutput is NULL, the return value indicates the /// number of supported resolutions. /// /// /// /// DC_EXTRA /// Returns the number of bytes required for the device-specific portion of the DEVMODE structure for the printer driver. /// /// /// DC_FIELDS /// /// Returns the dmFields member of the printer driver's DEVMODE structure. The dmFields member indicates which members in the /// device-independent portion of the structure are supported by the printer driver. /// /// /// /// DC_FILEDEPENDENCIES /// /// Retrieves the names of any additional files that need to be loaded when a driver is installed. The pOutput buffer receives an /// array of string buffers. Each string buffer is 64 characters long and contains the name of a file. The return value indicates /// the number of entries in the array. The name strings are null-terminated unless the name is 64 characters long. If pOutput is /// NULL, the return value is the number of files. /// /// /// /// DC_MAXEXTENT /// /// Returns the maximum paper size that the dmPaperLength and dmPaperWidth members of the printer driver's DEVMODE structure can /// specify. The LOWORD of the return value contains the maximum dmPaperWidth value, and the HIWORD contains the maximum /// dmPaperLength value. /// /// /// /// DC_MEDIAREADY /// /// Retrieves the names of the paper forms that are currently available for use. The pOutput buffer receives an array of string /// buffers. Each string buffer is 64 characters long and contains the name of a paper form. The return value indicates the number /// of entries in the array. The name strings are null-terminated unless the name is 64 characters long. If pOutput is NULL, the /// return value is the number of paper forms. /// /// /// /// DC_MEDIATYPENAMES /// /// Retrieves the names of the supported media types. The pOutput buffer receives an array of string buffers. Each string buffer is /// 64 characters long and contains the name of a supported media type. The return value indicates the number of entries in the /// array. The strings are null-terminated unless the name is 64 characters long. If pOutput is NULL, the return value is the number /// of media type names required. /// /// /// /// DC_MEDIATYPES /// /// Retrieves a list of supported media types. The pOutput buffer receives an array of DWORD values that indicate the supported /// media types. The return value indicates the number of entries in the array. For a list of possible array values, see the /// description of the dmMediaType member of the DEVMODE structure. If pOutput is NULL, the return value indicates the required /// number of entries in the array. /// /// /// /// DC_MINEXTENT /// /// Returns the minimum paper size that the dmPaperLength and dmPaperWidth members of the printer driver's DEVMODE structure can /// specify. The LOWORD of the return value contains the minimum dmPaperWidth value, and the HIWORD contains the minimum /// dmPaperLength value. /// /// /// /// DC_ORIENTATION /// /// Returns the relationship between portrait and landscape orientations for a device, in terms of the number of degrees that /// portrait orientation is rotated counterclockwise to produce landscape orientation. The return value can be one of the following: /// 0 No landscape orientation. 90 Portrait is rotated 90 degrees to produce landscape. 270 Portrait is rotated 270 degrees to /// produce landscape. /// /// /// /// DC_NUP /// /// Retrieves an array of integers that indicate that printer's ability to print multiple document pages per printed page. The /// pOutput buffer receives an array of DWORD values. Each value represents a supported number of document pages per printed page. /// The return value indicates the number of entries in the array. If pOutput is NULL, the return value indicates the required /// number of entries in the array. /// /// /// /// DC_PAPERNAMES /// /// Retrieves a list of supported paper names (for example, Letter or Legal). The pOutput buffer receives an array of string /// buffers. Each string buffer is 64 characters long and contains the name of a paper form. The return value indicates the number /// of entries in the array. The name strings are null-terminated unless the name is 64 characters long. If pOutput is NULL, the /// return value is the number of paper forms. /// /// /// /// DC_PAPERS /// /// Retrieves a list of supported paper sizes. The pOutput buffer receives an array of WORD values that indicate the available paper /// sizes for the printer. The return value indicates the number of entries in the array. For a list of the possible array values, /// see the description of the dmPaperSize member of the DEVMODE structure. If pOutput is NULL, the return value indicates the /// required number of entries in the array. /// /// /// /// DC_PAPERSIZE /// /// Retrieves the dimensions, in tenths of a millimeter, of each supported paper size. The pOutput buffer receives an array of POINT /// structures. Each structure contains the width (x-dimension) and length (y-dimension) of a paper size as if the paper were in the /// DMORIENT_PORTRAIT orientation. The return value indicates the number of entries in the array. /// /// /// /// DC_PERSONALITY /// /// Retrieves a list of printer description languages supported by the printer. The pOutput buffer receives an array of string /// buffers. Each buffer is 32 characters long and contains the name of a printer description language. The return value indicates /// the number of entries in the array. The name strings are null-terminated unless the name is 32 characters long. If pOutput is /// NULL, the return value indicates the required number of array entries. /// /// /// /// DC_PRINTERMEM /// The return value is the amount of available printer memory, in kilobytes. The pOutput parameter is not used. /// /// /// DC_PRINTRATE /// /// The return value indicates the printer's print rate. The value returned for DC_PRINTRATEUNIT indicates the units of the /// DC_PRINTRATE value. The pOutput parameter is not used. /// /// /// /// DC_PRINTRATEPPM /// The return value indicates the printer's print rate, in pages per minute. The pOutput parameter is not used. /// /// /// DC_PRINTRATEUNIT /// /// The return value is one of the following values that indicate the print rate units for the value returned for the DC_PRINTRATE /// flag. The pOutput parameter is not used. PRINTRATEUNIT_CPS Characters per second. PRINTRATEUNIT_IPM Inches per minute. /// PRINTRATEUNIT_LPM Lines per minute. PRINTRATEUNIT_PPM Pages per minute. /// /// /// /// DC_SIZE /// Returns the dmSize member of the printer driver's DEVMODE structure. /// /// /// DC_STAPLE /// /// If the printer supports stapling, the return value is a nonzero value; otherwise, the return value is zero. The pOutput /// parameter is not used. /// /// /// /// DC_TRUETYPE /// /// Retrieves the abilities of the driver to use TrueType fonts. For DC_TRUETYPE, the pOutput parameter should be NULL. The return /// value can be one or more of the following: DCTT_BITMAP Device can print TrueType fonts as graphics. DCTT_DOWNLOAD Device can /// download TrueType fonts. DCTT_SUBDEV Device can substitute device fonts for TrueType fonts. /// /// /// /// DC_VERSION /// Returns the specification version to which the printer driver conforms. /// /// /// /// /// A pointer to an array. The format of the array depends on the setting of the fwCapability parameter. See each capability above /// to find out what is returned if pOutput is NULL. /// /// /// A pointer to a DEVMODE structure. If this parameter is NULL, DeviceCapabilities retrieves the current default /// initialization values for the specified printer driver. Otherwise, the function retrieves the values contained in the structure /// to which pDevMode points. /// /// /// /// If the function succeeds, the return value depends on the setting of the fwCapability parameter. A return value of zero /// generally indicates that, while the function completed successfully, there was some type of failure, such as a capability that /// is not supported. For more details, see the descriptions for the fwCapability values. /// /// /// If the function returns -1, this may mean either that the capability is not supported or there was a general function failure. /// /// /// /// /// Note This is a blocking or synchronous function and might not return immediately. How quickly this function returns /// depends on run-time factors such as network status, print server configuration, and printer driver implementation—factors that /// are difficult to predict when writing an application. Calling this function from a thread that manages interaction with the user /// interface could make the application appear to be unresponsive. /// /// The DEVMODE structure pointed to by the pDevMode parameter may be obtained by calling the DocumentProperties function. /// /// If a printer driver supports custom device capabilities, the driver must call the SetPrinterData function for each custom /// capability. The SetPrinterData function adds the appropriate printer data to the print system, which enables 32-bit /// applications to access the custom capabilities on 64-bit Windows installations. /// /// /// For each custom capability, you must first add printer data that describes the type of the capability. To do this, when you call /// SetPrinterData, set the pValueName string to CustomDeviceCapabilityType_Xxx, where "Xxx" is the hexadecimal /// representation of the capability. For example, you might have "CustomDeviceCapabilityType_1234". The registry data that you set /// must be of the REG_DWORD type, and you must set its value to one of the following: /// /// /// /// 0, if the custom capability is a DWORD /// /// /// 1, if the custom capability is a buffer of bytes /// /// /// 2, if the custom capability is an array of items /// /// /// /// If the custom capability is an array of items, you must call SetPinterData a second time to provide information about the /// size of an item in the array. To do this, when you call SetPinterData, the pValueName string that you provide must be /// "CustomDeviceCapabilitySize_Xxx" where Xxx is the hexadecimal representation of the capability. For example, you might have /// "CustomDeviceCapabilitySize_1234". The registry data that you set must be of the REG_DWORD type, and you must set its /// value to the size in bytes of an item in the array. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-devicecapabilitiesa // int DeviceCapabilitiesA( LPCSTR pDevice, LPCSTR pPort, WORD fwCapability, LPSTR pOutput, const DEVMODEA *pDevMode ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("wingdi.h", MSDNShortId = "d7f63ef7-0a2e-47c3-9e81-6e8a6dffe9af")] public static extern int DeviceCapabilities(string pDevice, [Optional] string pPort, DC fwCapability, [Optional] IntPtr pOutput, [In, Optional] IntPtr pDevMode); /// The DocumentEvent function is an event handler for events associated with printing a document. /// /// A handle to a printer object. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// /// A device context handle that is generated by a call of CreateDC. This is zero if iEsc is set to /// DOCUMENTEVENT_CREATEDCPRE. For restrictions on printing from a 32-bit application on a 64-bit version of Windows, see Remarks. /// /// /// An escape code that identifies the event to be handled. This parameter can be one of the following integer constants. /// /// /// Constant /// Event /// /// /// DOCUMENTEVENT_ABORTDOC /// GDI is about to process a call to its AbortDoc function. /// /// /// DOCUMENTEVENT_CREATEDCPOST /// /// GDI has just processed a call to its CreateDC or CreateIC function. This escape code should not be used unless there has been a /// previous call to DocumentEvent with iEsc set to DOCUMENTEVENT_CREATEDCPRE. /// /// /// /// DOCUMENTEVENT_CREATEDCPRE /// GDI is about to process a call to its CreateDC or CreateIC function. /// /// /// DOCUMENTEVENT_DELETEDC /// GDI is about to process a call to its DeleteDC function. /// /// /// DOCUMENTEVENT_ENDDOCPOST /// GDI has just processed a call to its EndDoc function. /// /// /// DOCUMENTEVENT_ENDDOCPRE or DOCUMENTEVENT_ENDDOC /// GDI is about to process a call to its EndDoc function. /// /// /// DOCUMENTEVENT_ENDPAGE /// GDI is about to process a call to its EndPage function. /// /// /// DOCUMENTEVENT_ESCAPE /// GDI is about to process a call to its ExtEscape function. /// /// /// DOCUMENTEVENT_QUERYFILTER /// /// The DOCUMENTEVENT_QUERYFILTER event represents an opportunity for the spooler to query the driver for a list of the /// DOCUMENTEVENT_ XXX events to which the driver will respond. This event is issued just prior to a call to DocumentEvent that /// passes the DOCUMENTEVENT_CREATEDCPRE event. /// /// /// /// DOCUMENTEVENT_RESETDCPOST /// /// GDI has just processed a call to its ResetDC function. This escape code should not be used unless there has been a previous call /// to DocumentEvent with iEsc set to DOCUMENTEVENT_RESETDCPRE. /// /// /// /// DOCUMENTEVENT_RESETDCPRE /// GDI is about to process a call to its ResetDC function. /// /// /// DOCUMENTEVENT_STARTDOCPOST /// GDI has just processed a call to its StartDoc function. /// /// /// DOCUMENTEVENT_STARTDOCPRE or DOCUMENTEVENT_STARTDOC /// GDI is about to process a call to its StartDoc function. /// /// /// DOCUMENTEVENT_STARTPAGE /// GDI is about to process a call to its StartPage function. /// /// /// /// The size, in bytes, of the buffer pointed to by pvIn. /// /// A pointer to a buffer. What the buffer contains depends on the value of iEsc, as shown in the following table. /// /// /// Constant /// pvin Contents /// /// /// DOCUMENTEVENT_ABORTDOC /// Not used. /// /// /// DOCUMENTEVENT_CREATEDCPOST /// /// pvIn contains the address of a pointer to the DEVMODE structure specified in the pvOut parameter in a previous call to this /// function, for which the iEsc parameter was set to DOCUMENTEVENT_CREATEDCPRE. /// /// /// /// DOCUMENTEVENT_CREATEDCPRE /// pvIn points to a DOCEVENT_CREATEDCPRE structure which is documented in the Windows Driver Development Kit. /// /// /// DOCUMENTEVENT_DELETEDC /// Not used. /// /// /// DOCUMENTEVENT_ENDDOCPOST /// Not used. /// /// /// DOCUMENTEVENT_ENDDOCPRE or DOCUMENTEVENT_ENDDOC /// Not used. /// /// /// DOCUMENTEVENT_ENDPAGE /// Not used. /// /// /// DOCUMENTEVENT_ESCAPE /// pvIn points to a DOCEVENT_ESCAPE structure which is documented in the Windows Driver Development Kit. /// /// /// DOCUMENTEVENT_QUERYFILTER /// Same as for DOCUMENTEVENT_CREATEDCPRE. /// /// /// DOCUMENTEVENT_RESETDCPOST /// /// pvIn contains the address of a pointer to the DEVMODE structure specified in the pvOut parameter in a previous call to this /// function, for which the iEsc parameter was set to DOCUMENTEVENT_RESETDCPRE. /// /// /// /// DOCUMENTEVENT_RESETDCPRE /// pvIn contains the address of a pointer to the DEVMODE structure supplied by the caller of ResetDC. /// /// /// DOCUMENTEVENT_STARTDOCPOST /// pvIn points to a LONG that specifies the print job identifier returned by StartDoc. /// /// /// DOCUMENTEVENT_STARTDOCPRE or DOCUMENTEVENT_STARTDOC /// pvIn contains the address of a pointer to a DOCINFO structure supplied by the caller of StartDoc. /// /// /// DOCUMENTEVENT_STARTPAGE /// Not used. /// /// /// /// /// /// /// Value /// Meaning /// /// /// IDOCUMENTEVENT_QUERYFILTER /// The size, in bytes, of the buffer pointer to by pvOut. /// /// /// DOCUMENTEVENT_ESCAPE /// A value that is used as the cbOutput parameter for ExtEscape. /// /// /// For all other values /// iEsc is not used. /// /// /// /// /// A pointer to a buffer. The contents of the buffer depend on the value supplied for iEsc, as shown in the following table. /// /// /// Constant /// pvOut Contents /// /// /// DOCUMENTEVENT_CREATEDCPRE /// /// A pointer to a driver-supplied DEVMODE structure, which GDI uses instead of the one supplied by the CreateDC caller. (If NULL, /// GDI uses the caller-supplied structure.) /// /// /// /// DOCUMENTEVENT_ESCAPE /// A pointer to a buffer that is used as the lpszOutData parameter for ExtEscape. /// /// /// DOCUMENTEVENT_QUERYFILTER /// A pointer to buffer containing a DOCEVENT_FILTER structure which is documented in the Windows Driver Development Kit. /// /// /// DOCUMENTEVENT_RESETDCPRE /// /// A pointer to a driver-supplied DEVMODE structure, which GDI uses instead of the one supplied by the ResetDC caller. (If NULL, /// GDI uses the caller-supplied structure.) /// /// /// /// /// /// /// The function's return value is dependent on the escape supplied for iEsc. For some escape codes, the return value is not used /// (see below). If the function supplies a return value, it must be one of the following. /// /// /// /// Return Value /// Meaning /// /// /// DOCUMENTEVENT_FAILURE /// The driver supports the escape code identified by iEsc, but a failure occurred. /// /// /// DOCUMENTEVENT_SUCCESS /// The driver successfully handled the escape code identified by iEsc. /// /// /// DOCUMENTEVENT_UNSUPPORTED /// The driver does not support the escape code identified by iEsc. /// /// /// /// The following list indicates which escape codes that require a return value and which do not, and explains the meaning of the /// DOCUMENTEVENT_SUCCESS, DOCUMENTEVENT_FAILURE, and DOCUMENTEVENT_UNSUPPORTED return codes. /// /// /// /// Return Value /// Meaning /// /// /// DOCUMENTEVENT_ABORTDOC /// The return value is not used and should not be read. /// /// /// DOCUMENTEVENT_CREATEDCPOST /// The return value is not used and should not be read. /// /// /// DOCUMENTEVENT_CREATEDCPRE /// /// DOCUMENTEVENT_FAILURE - GDI does not create the device context or information context, and provides a return value of 0 for /// CreateDC or CreateIC. /// /// /// /// DOCUMENTEVENT_DELETEDC /// The return value is not used and should not be read. /// /// /// DOCUMENTEVENT_ENDDOCPOST /// The return value is not used and should not be read. /// /// /// DOCUMENTEVENT_ENDDOCPRE or DOCUMENTEVENT_ENDDOC /// The return value is not used and should not be read. /// /// /// DOCUMENTEVENT_ENDPAGE /// The return value is not used and should not be read. /// /// /// DOCUMENTEVENT_ESCAPE /// The return value is not used and should not be read. /// /// /// DOCUMENTEVENT_QUERYFILTER /// See Remarks. /// /// /// DOCUMENTEVENT_RESETDCPOST /// The return value is not used and should not be read. /// /// /// DOCUMENTEVENT_RESETDCPRE /// DOCUMENTEVENT_FAILURE - GDI does not reset the device context, and provides a return value of 0 for ResetDC. /// /// /// DOCUMENTEVENT_STARTDOCPOST /// DOCUMENTEVENT_FAILURE - GDI calls AbortDoc to stop the document, and then provides a return value of SP_ERROR for StartDoc. /// /// /// DOCUMENTEVENT_STARTDOCPRE or DOCUMENTEVENT_STARTDOC /// DOCUMENTEVENT_FAILURE - GDI does not start the document, and provides a return value of SP_ERROR for StartDoc. /// /// /// DOCUMENTEVENT_STARTPAGE /// DOCUMENTEVENT_FAILURE - GDI does not start the page, and provides a return value of SP_ERROR for StartPage. /// /// /// /// /// /// For an iEsc value of DOCUMENTEVENT_QUERYFILTER, the spooler can interpret a DOCUMENTEVENT_SUCCESS value returned by /// DocumentEvent in two ways, depending on whether the driver modified certain members of the DOCEVENT_FILTER structure /// (which is documented in the Windows Driver Development Kit ). (The pvOut parameter points to this structure.) When the spooler /// allocates memory for a structure of this type, it initializes two members of this structure, cElementsReturned and /// cElementsNeeded, to known values. After DocumentEvent returns, the spooler determines whether the values of these /// members have changed, and uses that information to interpret the DocumentEvent return value. The following table /// summarizes this situation. /// /// /// /// Return Value /// Status of cElementsReturned and cElementsNeeded /// Meaning /// /// /// DOCUMENTEVENT_SUCCESS /// Driver made no change to either member. /// /// The spooler interprets this return value as equivalent to DOCUMENTEVENT_UNSUPPORTED. The spooler is unable to retrieve the event /// filter from the driver, so it persists in calling DocumentEvent for all events. /// /// /// /// DOCUMENTEVENT_SUCCESS /// Driver wrote to one or both members. /// /// The spooler accepts this return value without interpretation. If the driver wrote to only one of cElementsNeeded and /// cElementsReturned, the spooler considers the unchanged member to have a value of zero. The spooler filters out all events listed /// in the aDocEventCall member of DOCEVENT_FILTER (which is documented in the Windows Driver Development Kit ). /// /// /// /// DOCUMENTEVENT_UNSUPPORTED /// Not applicable /// /// The driver does not support DOCUMENTEVENT_QUERYFILTER. The spooler is unable to retrieve the event filter from the driver, so it /// persists in calling DocumentEvent for all events. /// /// /// /// DOCUMENTEVENT_FAILURE /// Not applicable /// /// The driver supports DOCUMENTEVENT_QUERYFILTER, but encountered an internal error. The spooler is unable to retrieve the event /// filter from the driver, so it persists in calling DocumentEvent for all events. /// /// /// /// If the escape code supplied in the iEsc parameter is DOCUMENTEVENT_CREATEDCPRE, the following rules apply: /// /// /// /// If the job is being sent directly to the printer without spooling, pvIn->pszDevice points to the printer name. (For more /// information, see the documentation for the DOCEVENT_CREATEDCPRE structure in the Windows Driver Development Kit.) /// /// /// /// If the job is being spooled, pvIn->pszDevice points to the printer port name. /// /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/documentevent HRESULT DocumentEvent( _In_ HANDLE hPrinter, _In_ HDC hdc, // INT iEsc, ULONG cbIn, _In_ PVOID pvIn, ULONG cbOut, _Out_ PVOID pvOut ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "1250116e-55c7-470f-97f6-36f27a31a841")] public static extern HRESULT DocumentEvent(HPRINTER hPrinter, HDC hdc, DOCUMENTEVENT iEsc, uint cbIn, IntPtr pvIn, uint cbOut, IntPtr pvOut); /// /// The DocumentProperties function retrieves or modifies printer initialization information or displays a /// printer-configuration property sheet for the specified printer. /// /// A handle to the parent window of the printer-configuration property sheet. /// /// A handle to a printer object. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// /// A pointer to a null-terminated string that specifies the name of the device for which the printer-configuration property sheet /// is displayed. /// /// /// A pointer to a DEVMODE structure that receives the printer configuration data specified by the user. /// /// /// A pointer to a DEVMODE structure that the operating system uses to initialize the property sheet controls. /// /// This parameter is only used if the DM_IN_BUFFER flag is set in the fMode parameter. If DM_IN_BUFFER is not set, /// the operating system uses the printer's default DEVMODE. /// /// /// /// /// The operations the function performs. If this parameter is zero, the DocumentProperties function returns the number of /// bytes required by the printer driver's DEVMODE data structure. Otherwise, use one or more of the following constants to /// construct a value for this parameter; note, however, that in order to change the print settings, an application must specify at /// least one input value and one output value. /// /// /// /// Value /// Meaning /// /// /// DM_IN_BUFFER /// /// Input value. Before prompting, copying, or updating, the function merges the printer driver's current print settings with the /// settings in the DEVMODE structure specified by the pDevModeInput parameter. The function updates the structure only for those /// members specified by the DEVMODE structure's dmFields member. This value is also defined as DM_MODIFY. In cases of conflict /// during the merge, the settings in the DEVMODE structure specified by pDevModeInput override the printer driver's current print settings. /// /// /// /// DM_IN_PROMPT /// /// Input value. The function presents the printer driver's Print Setup property sheet and then changes the settings in the /// printer's DEVMODE data structure to those values specified by the user. This value is also defined as DM_PROMPT. /// /// /// /// DM_OUT_BUFFER /// /// Output value. The function writes the printer driver's current print settings, including private data, to the DEVMODE data /// structure specified by the pDevModeOutput parameter. The caller must allocate a buffer sufficiently large to contain the /// information. If the bit DM_OUT_BUFFER sets is clear, the pDevModeOutput parameter can be NULL. This value is also defined as DM_COPY. /// /// /// /// /// /// /// If the fMode parameter is zero, the return value is the size of the buffer required to contain the printer driver initialization /// data. Note that this buffer can be larger than a DEVMODE structure if the printer driver appends private data to the structure. /// /// /// If the function displays the property sheet, the return value is either IDOK or IDCANCEL, depending on which /// button the user selects. /// /// If the function does not display the property sheet and is successful, the return value is IDOK. /// If the function fails, the return value is less than zero. /// /// /// The string pointed to by the pDeviceName parameter can be obtained by calling the GetPrinter function. /// /// The DEVMODE structure actually used by a printer driver contains the device-independent part (as defined above) followed /// by a driver-specific part that varies in size and content with each driver and driver version. Because of this driver /// dependence, it is very important for applications to query the driver for the correct size of the DEVMODE structure /// before allocating a buffer for it. /// /// To make changes to print settings that are local to an application, an application should follow these steps: /// /// /// /// Get the number of bytes required for the full DEVMODE structure by calling DocumentProperties and specifying zero /// in the fMode parameter. /// /// /// /// Allocate memory for the full DEVMODE structure. /// /// /// /// Get the current printer settings by calling DocumentProperties. Pass a pointer to the DEVMODE structure allocated /// in Step 2 as the pDevModeOutput parameter and specify the DM_OUT_BUFFER value. /// /// /// /// /// Modify the appropriate members of the returned DEVMODE structure and indicate which members were changed by setting the /// corresponding bits in the dmFields member of the DEVMODE. /// /// /// /// /// Call DocumentProperties and pass the modified DEVMODE structure back as both the pDevModeInput and pDevModeOutput /// parameters and specify both the DM_IN_BUFFER and DM_OUT_BUFFER values (which are combined using the OR /// operator).The DEVMODE structure returned by the third call to DocumentProperties can be used as an argument in a /// call to the CreateDC function. /// /// /// /// /// To create a handle to a printer-device context using the current printer settings, you only need to call /// DocumentProperties twice, as described above. The first call gets the size of the full DEVMODE and the second call /// initializes the DEVMODE with the current printer settings. Pass the initialized DEVMODE to CreateDC to /// obtain the handle to the printer device context. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/documentproperties LONG DocumentProperties( _In_ HWND hWnd, _In_ HANDLE // hPrinter, _In_ LPTSTR pDeviceName, _Out_ PDEVMODE pDevModeOutput, _In_ PDEVMODE pDevModeInput, _In_ DWORD fMode ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "e89a2f6f-2bac-4369-b526-f8e15028698b")] public static extern int DocumentProperties(HWND hWnd, HPRINTER hPrinter, string pDeviceName, IntPtr pDevModeOutput, in DEVMODE pDevModeInput, DM fMode); /// /// The DocumentProperties function retrieves or modifies printer initialization information or displays a /// printer-configuration property sheet for the specified printer. /// /// A handle to the parent window of the printer-configuration property sheet. /// /// A handle to a printer object. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// /// A pointer to a null-terminated string that specifies the name of the device for which the printer-configuration property sheet /// is displayed. /// /// /// A pointer to a DEVMODE structure that receives the printer configuration data specified by the user. /// /// /// A pointer to a DEVMODE structure that the operating system uses to initialize the property sheet controls. /// /// This parameter is only used if the DM_IN_BUFFER flag is set in the fMode parameter. If DM_IN_BUFFER is not set, /// the operating system uses the printer's default DEVMODE. /// /// /// /// /// The operations the function performs. If this parameter is zero, the DocumentProperties function returns the number of /// bytes required by the printer driver's DEVMODE data structure. Otherwise, use one or more of the following constants to /// construct a value for this parameter; note, however, that in order to change the print settings, an application must specify at /// least one input value and one output value. /// /// /// /// Value /// Meaning /// /// /// DM_IN_BUFFER /// /// Input value. Before prompting, copying, or updating, the function merges the printer driver's current print settings with the /// settings in the DEVMODE structure specified by the pDevModeInput parameter. The function updates the structure only for those /// members specified by the DEVMODE structure's dmFields member. This value is also defined as DM_MODIFY. In cases of conflict /// during the merge, the settings in the DEVMODE structure specified by pDevModeInput override the printer driver's current print settings. /// /// /// /// DM_IN_PROMPT /// /// Input value. The function presents the printer driver's Print Setup property sheet and then changes the settings in the /// printer's DEVMODE data structure to those values specified by the user. This value is also defined as DM_PROMPT. /// /// /// /// DM_OUT_BUFFER /// /// Output value. The function writes the printer driver's current print settings, including private data, to the DEVMODE data /// structure specified by the pDevModeOutput parameter. The caller must allocate a buffer sufficiently large to contain the /// information. If the bit DM_OUT_BUFFER sets is clear, the pDevModeOutput parameter can be NULL. This value is also defined as DM_COPY. /// /// /// /// /// /// /// If the fMode parameter is zero, the return value is the size of the buffer required to contain the printer driver initialization /// data. Note that this buffer can be larger than a DEVMODE structure if the printer driver appends private data to the structure. /// /// /// If the function displays the property sheet, the return value is either IDOK or IDCANCEL, depending on which /// button the user selects. /// /// If the function does not display the property sheet and is successful, the return value is IDOK. /// If the function fails, the return value is less than zero. /// /// /// The string pointed to by the pDeviceName parameter can be obtained by calling the GetPrinter function. /// /// The DEVMODE structure actually used by a printer driver contains the device-independent part (as defined above) followed /// by a driver-specific part that varies in size and content with each driver and driver version. Because of this driver /// dependence, it is very important for applications to query the driver for the correct size of the DEVMODE structure /// before allocating a buffer for it. /// /// To make changes to print settings that are local to an application, an application should follow these steps: /// /// /// /// Get the number of bytes required for the full DEVMODE structure by calling DocumentProperties and specifying zero /// in the fMode parameter. /// /// /// /// Allocate memory for the full DEVMODE structure. /// /// /// /// Get the current printer settings by calling DocumentProperties. Pass a pointer to the DEVMODE structure allocated /// in Step 2 as the pDevModeOutput parameter and specify the DM_OUT_BUFFER value. /// /// /// /// /// Modify the appropriate members of the returned DEVMODE structure and indicate which members were changed by setting the /// corresponding bits in the dmFields member of the DEVMODE. /// /// /// /// /// Call DocumentProperties and pass the modified DEVMODE structure back as both the pDevModeInput and pDevModeOutput /// parameters and specify both the DM_IN_BUFFER and DM_OUT_BUFFER values (which are combined using the OR /// operator).The DEVMODE structure returned by the third call to DocumentProperties can be used as an argument in a /// call to the CreateDC function. /// /// /// /// /// To create a handle to a printer-device context using the current printer settings, you only need to call /// DocumentProperties twice, as described above. The first call gets the size of the full DEVMODE and the second call /// initializes the DEVMODE with the current printer settings. Pass the initialized DEVMODE to CreateDC to /// obtain the handle to the printer device context. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/documentproperties LONG DocumentProperties( _In_ HWND hWnd, _In_ HANDLE // hPrinter, _In_ LPTSTR pDeviceName, _Out_ PDEVMODE pDevModeOutput, _In_ PDEVMODE pDevModeInput, _In_ DWORD fMode ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "e89a2f6f-2bac-4369-b526-f8e15028698b")] public static extern int DocumentProperties(HWND hWnd, HPRINTER hPrinter, string pDeviceName, IntPtr pDevModeOutput, [Optional] IntPtr pDevModeInput, DM fMode); /// The EndDocPrinter function ends a print job for the specified printer. /// /// Handle to a printer for which the print job should be ended. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// The EndDocPrinter function returns an error if the print job was not started by calling the StartDocPrinter function. /// /// The sequence for a print job is as follows: /// /// /// To begin a print job, call StartDocPrinter. /// /// /// To begin each page, call StartPagePrinter. /// /// /// To write data to a page, call WritePrinter. /// /// /// To end each page, call EndPagePrinter. /// /// /// Repeat 2, 3, and 4 for as many pages as necessary. /// /// /// To end the print job, call EndDocPrinter. /// /// /// /// When a page in a spooled file exceeds approximately 350 MB, it may fail to print and not send an error message. For example, /// this can occur when printing large EMF files. The page size limit depends on many factors including the amount of virtual memory /// available, the amount of memory allocated by calling processes, and the amount of fragmentation in the process heap. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/enddocprinter BOOL EndDocPrinter( _In_ HANDLE hPrinter ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "13c713e8-cc24-4191-8b1e-967b9e20e541")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EndDocPrinter(HPRINTER hPrinter); /// /// The EndPagePrinter function notifies the print spooler that the application is at the end of a page in a print job. /// /// /// Handle to the printer for which the page will be concluded. Use the OpenPrinter or AddPrinter function to retrieve /// a printer handle. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// The sequence for a print job is as follows: /// /// /// To begin a print job, call StartDocPrinter. /// /// /// To begin each page, call StartPagePrinter. /// /// /// To write data to a page, call WritePrinter. /// /// /// To end each page, call EndPagePrinter. /// /// /// Repeat 2, 3, and 4 for as many pages as necessary. /// /// /// To end the print job, call EndDocPrinter. /// /// /// /// When a page in a spooled file exceeds approximately 350 MB, it can fail to print and not send an error message. For example, /// this can occur when printing large EMF files. The page size limit depends on many factors including the amount of virtual memory /// available, the amount of memory allocated by calling processes, and the amount of fragmentation in the process heap. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/endpageprinter BOOL EndPagePrinter( _In_ HANDLE hPrinter ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "aceb88b9-375b-4cd2-996a-c369f590154e")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EndPagePrinter(HPRINTER hPrinter); /// The EnumForms function enumerates the forms supported by the specified printer. /// /// Handle to the printer for which the forms should be enumerated. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// Specifies the version of the structure to which pForm points. This value must be 1 or 2. /// /// Pointer to one or more FORM_INFO_1 structures or to one or more FORM_INFO_2 structures. All the structures will /// have the same level. /// /// Specifies the size, in bytes, of the buffer to which pForm points. /// /// Pointer to a variable that receives the number of bytes copied to the array to which pForm points (if the operation succeeds) or /// the number of bytes required (if it fails because cbBuf is too small). /// /// /// Pointer to a variable that receives the number of structures copied into the array to which pForm points. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// If the caller is remote, and the Level is 2, the StringType value of the returned FORM_INFO_2 structures will /// always be STRING_LANGPAIR. /// /// /// In Windows Vista, the form data returned by EnumForms is retrieved from a local cache when hPrinter refers to a remote /// print server or a printer hosted by a print server and there is at least one open connection to a printer on the remote print /// server. In all other configurations, the form data is queried from the remote print server. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/enumforms BOOL EnumForms( _In_ HANDLE hPrinter, _In_ DWORD Level, _Out_ // LPBYTE pForm, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded, _Out_ LPDWORD pcReturned ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "b13b515a-c764-4a80-ab85-95fb4abb2a6b")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnumForms(HPRINTER hPrinter, uint Level, IntPtr pForm, uint cbBuf, out uint pcbNeeded, out uint pcReturned); /// The EnumForms function enumerates the forms supported by the specified printer. /// The type of form information to enumerate. This must be either FORM_INFO_1 or FORM_INFO_2. /// /// Handle to the printer for which the forms should be enumerated. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// A sequence of FORM_INFO_1 or FORM_INFO_2 structures. All the structures will be of . [PInvokeData("winspool.h", MSDNShortId = "b13b515a-c764-4a80-ab85-95fb4abb2a6b")] public static IEnumerable EnumForms(HPRINTER hPrinter) where T : struct { if (!TryGetLevel("FORM_INFO_", out var lvl)) throw new ArgumentException($"{nameof(EnumForms)} cannot process a structure of type {typeof(T).Name}."); if (!EnumForms(hPrinter, lvl, default, 0, out var bytes, out var count)) Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_INSUFFICIENT_BUFFER); if (bytes == 0) return new T[0]; using var mem = new SafeCoTaskMemHandle(bytes); if (!EnumForms(hPrinter, lvl, mem, mem.Size, out bytes, out count)) Win32Error.ThrowLastError(); return mem.ToArray((int)count); } /// The EnumJobs function retrieves information about a specified set of print jobs for a specified printer. /// /// A handle to the printer object whose print jobs the function enumerates. Use the OpenPrinter or AddPrinter /// function to retrieve a printer handle. /// /// /// The zero-based position within the print queue of the first print job to enumerate. For example, a value of 0 specifies that /// enumeration should begin at the first print job in the print queue; a value of 9 specifies that enumeration should begin at the /// tenth print job in the print queue. /// /// The total number of print jobs to enumerate. /// /// The type of information returned in the pJob buffer. /// /// /// Value /// Meaning /// /// /// 1 /// pJob receives an array of JOB_INFO_1 structures /// /// /// 2 /// pJob receives an array of JOB_INFO_2 structures /// /// /// 3 /// pJob receives an array of JOB_INFO_3 structures /// /// /// /// /// /// A pointer to a buffer that receives an array of JOB_INFO_1, JOB_INFO_2, or JOB_INFO_3 structures. The /// buffer must be large enough to receive the array of structures and any strings or other data to which the structure members point. /// /// /// To determine the required buffer size, call EnumJobs with cbBuf set to zero. EnumJobs fails, GetLastError /// returns ERROR_INSUFFICIENT_BUFFER, and the pcbNeeded parameter returns the size, in bytes, of the buffer required to hold the /// array of structures and their data. /// /// /// The size, in bytes, of the pJob buffer. /// /// A pointer to a variable that receives the number of bytes copied if the function succeeds. If the function fails, the variable /// receives the number of bytes required. /// /// /// A pointer to a variable that receives the number of JOB_INFO_1, JOB_INFO_2, or JOB_INFO_3 structures /// returned in the pJob buffer. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// The JOB_INFO_1 structure contains general print-job information; the JOB_INFO_2 structure has much more detailed /// information. The JOB_INFO_3 structure contains information about how jobs are linked. /// /// /// To determine the number of print jobs in the printer queue, call the GetPrinter function with the Level parameter set to 2. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/enumjobs BOOL EnumJobs( _In_ HANDLE hPrinter, _In_ DWORD FirstJob, _In_ // DWORD NoJobs, _In_ DWORD Level, _Out_ LPBYTE pJob, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded, _Out_ LPDWORD pcReturned ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "1cf429ea-b40e-4063-b6de-c43b7b87f3d3")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnumJobs(HPRINTER hPrinter, uint FirstJob, uint NoJobs, uint Level, IntPtr pJob, uint cbBuf, out uint pcbNeeded, out uint pcReturned); /// The EnumJobs function retrieves information about a specified set of print jobs for a specified printer. /// /// The type of form information to enumerate. This must be either JOB_INFO_1, JOB_INFO_2, or JOB_INFO_3. /// /// /// A handle to the printer object whose print jobs the function enumerates. Use the OpenPrinter or AddPrinter /// function to retrieve a printer handle. /// /// /// The zero-based position within the print queue of the first print job to enumerate. For example, a value of 0 specifies that /// enumeration should begin at the first print job in the print queue; a value of 9 specifies that enumeration should begin at the /// tenth print job in the print queue. /// /// The total number of print jobs to enumerate. /// /// A sequence of JOB_INFO_1, JOB_INFO_2, or JOB_INFO_3 structures. All the structures will be of . /// [PInvokeData("winspool.h", MSDNShortId = "1cf429ea-b40e-4063-b6de-c43b7b87f3d3")] public static IEnumerable EnumJobs(HPRINTER hPrinter, uint FirstJob = 0, uint NoJobs = uint.MaxValue) where T : struct { if (!TryGetLevel("JOB_INFO_", out var lvl)) throw new ArgumentException($"{nameof(EnumJobs)} cannot process a structure of type {typeof(T).Name}."); if (!EnumJobs(hPrinter, FirstJob, NoJobs, lvl, default, 0, out var bytes, out var count)) Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_INSUFFICIENT_BUFFER); if (bytes == 0) return new T[0]; using var mem = new SafeCoTaskMemHandle(bytes); if (!EnumJobs(hPrinter, FirstJob, NoJobs, lvl, mem, mem.Size, out bytes, out count)) Win32Error.ThrowLastError(); return mem.ToArray((int)count); } /// /// The EnumPrinterData function enumerates configuration data for a specified printer. /// To retrieve the configuration data in a single call, use the EnumPrinterDataEx function. /// /// /// A handle to the printer whose configuration data is to be obtained. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// /// An index value that specifies the configuration data value to retrieve. /// /// Set this parameter to zero for the first call to EnumPrinterData for a specified printer handle. Then increment the /// parameter by one for subsequent calls involving the same printer, until the function returns ERROR_NO_MORE_ITEMS. See the /// following Remarks section for further information. /// /// /// If you use the technique mentioned in the descriptions of the cbValueName and cbData parameters to obtain adequate buffer size /// values, setting both those parameters to zero in a first call to EnumPrinterData for a specified printer handle, the /// value of dwIndex does not matter for that call. Set dwIndex to zero in the next call to EnumPrinterData to start the /// actual enumeration process. /// /// /// Configuration data values are not ordered. New values will have an arbitrary index. This means that the EnumPrinterData /// function may return values in any order. /// /// /// /// A pointer to a buffer that receives the name of the configuration data value, including a terminating null character. /// /// /// The size, in bytes, of the buffer pointed to by pValueName. /// /// If you want to have the operating system supply an adequate buffer size, set both this parameter and the cbData parameter to /// zero for the first call to EnumPrinterData for a specified printer handle. When the function returns, the variable /// pointed to by pcbValueName will contain a buffer size that is large enough to successfully enumerate all of the printer's /// configuration data value names. /// /// /// A pointer to a variable that receives the number of bytes stored into the buffer pointed to by pValueName. /// /// A pointer to a variable that receives a code indicating the type of data stored in the specified value. For a list of the /// possible type codes, see Registry Value Types. The pType parameter can be NULL if the type code is not required. /// /// /// A pointer to a buffer that receives the configuration data value. /// This parameter can be NULL if the configuration data value is not required. /// /// /// The size, in bytes, of the buffer pointed to by pData. /// /// If you want to have the operating system supply an adequate buffer size, set both this parameter and the cbValueName parameter /// to zero for the first call to EnumPrinterData for a specified printer handle. When the function returns, the variable /// pointed to by pcbData will contain a buffer size that is large enough to successfully enumerate all of the printer's /// configuration data value names. /// /// /// /// A pointer to a variable that receives the number of bytes stored into the buffer pointed to by pData. /// This parameter can be NULL if pData is NULL. /// /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is a system error code. /// /// The function returns ERROR_NO_MORE_ITEMS when there are no more configuration data values to retrieve for a specified printer handle. /// /// /// /// /// EnumPrinterData retrieves printer configuration data set by the SetPrinterData function. A printer's configuration /// data consists of a set of named and typed values. The EnumPrinterData function obtains one of these values, and its name /// and a type code, each time you call it. Call the EnumPrinterData function several times in succession to obtain all of a /// printer's configuration data values. /// /// /// Printer configuration data is stored in the registry. While enumerating printer configuration data, you should avoid calling /// registry functions that might change that data. /// /// /// If you want to have the operating system supply an adequate buffer size, first call EnumPrinterData with both the /// cbValueName and cbData parameters set to zero, as noted earlier in the Parameters section. The value of dwIndex does not matter /// for this call. When the function returns, *pcbValueName and *pcbData will contain buffer sizes that are large enough to /// enumerate all of the printer's configuration data value names and values. On the next call, allocate value name and data /// buffers, set cbValueName and cbData to the sizes in bytes of the allocated buffers, and set dwIndex to zero. Thereafter, /// continue to call the EnumPrinterData function, incrementing dwIndex by one each time, until the function returns ERROR_NO_MORE_ITEMS. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/enumprinterdata DWORD EnumPrinterData( _In_ HANDLE hPrinter, _In_ DWORD // dwIndex, _Out_ LPTSTR pValueName, _In_ DWORD cbValueName, _Out_ LPDWORD pcbValueName, _Out_ LPDWORD pType, _Out_ LPBYTE pData, // _In_ DWORD cbData, _Out_ LPDWORD pcbData ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "0a4c8436-46fe-4e21-8d55-c5031a3d1b38")] public static extern Win32Error EnumPrinterData(HPRINTER hPrinter, uint dwIndex, StringBuilder pValueName, uint cbValueName, out uint pcbValueName, out REG_VALUE_TYPE pType, IntPtr pData, uint cbData, out uint pcbData); /// /// The EnumPrinterData function enumerates configuration data for a specified printer. /// To retrieve the configuration data in a single call, use the EnumPrinterDataEx function. /// /// /// A handle to the printer whose configuration data is to be obtained. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// /// A sequence of tuples, each with the following information. /// /// /// valueName ( ) /// The name of the configuration data value. /// /// /// valueType ( ) /// The type of data stored in the specified value. /// /// /// value ( ) /// The configuration data value. /// /// /// [PInvokeData("winspool.h", MSDNShortId = "0a4c8436-46fe-4e21-8d55-c5031a3d1b38")] public static IEnumerable<(string valueName, REG_VALUE_TYPE valueType, object value)> EnumPrinterData(HPRINTER hPrinter) { var idx = 0U; EnumPrinterData(hPrinter, idx, null, 0, out var valueNameSz, out _, default, 0, out var dataSz).ThrowIfFailed(); if (valueNameSz == 0) yield break; var name = new StringBuilder(1024); using var mem = new SafeCoTaskMemHandle(dataSz); while (true) { name.EnsureCapacity((int)valueNameSz); if (mem.Size < dataSz) mem.Size = dataSz; var ret = EnumPrinterData(hPrinter, idx, name, (uint)name.Capacity, out valueNameSz, out var valueType, mem, mem.Size, out dataSz); if (ret == Win32Error.ERROR_NO_MORE_ITEMS) break; if (ret == Win32Error.ERROR_MORE_DATA) continue; ret.ThrowIfFailed(); if (valueNameSz == 0) continue; ++idx; yield return (name.ToString(), valueType, valueType.GetValue(mem, mem.Size)); } } /// /// The EnumPrinterDataEx function enumerates all value names and data for a specified printer and key. /// /// Printer data is stored in the registry. While enumerating printer data, do not call registry functions that might change the data. /// /// /// /// A handle to the printer for which the function retrieves configuration data. Use the OpenPrinter or AddPrinter /// function to retrieve a printer handle. /// /// /// /// A pointer to a null-terminated string that specifies the key containing the values to enumerate. Use the backslash ( \ ) /// character as a delimiter to specify a path with one or more subkeys. EnumPrinterDataEx enumerates all values of the key, /// but does not enumerate values of subkeys of the specified key. Use the EnumPrinterKey function to enumerate subkeys. /// /// If pKeyName is NULL or an empty string, EnumPrinterDataEx returns ERROR_INVALID_PARAMETER. /// /// /// A pointer to a buffer that receives an array of PRINTER_ENUM_VALUES structures. Each structure contains the value name, /// type, data, and sizes of a value under the key. /// /// /// The size, in bytes, of the buffer pointed to by pcbEnumValues. If you set cbEnumValues to zero, the pcbEnumValues parameter /// returns the required buffer size. /// /// /// A pointer to a variable that receives the size, in bytes, of the retrieved configuration data. If the buffer size specified by /// cbEnumValues is too small, the function returns ERROR_MORE_DATA and pcbEnumValues indicates the required buffer size. /// /// /// A pointer to a variable that receives the number of PRINTER_ENUM_VALUES structures returned in pEnumValues. /// /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is a system error code. /// /// /// EnumPrinterDataEx retrieves printer configuration data set by the SetPrinterDataEx and SetPrinterData functions. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/enumprinterdataex DWORD EnumPrinterDataEx( _In_ HANDLE hPrinter, _In_ // LPCTSTR pKeyName, _Out_ LPBYTE pEnumValues, _In_ DWORD cbEnumValues, _Out_ LPDWORD pcbEnumValues, _Out_ LPDWORD pnEnumValues ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "bc5ecc46-24a4-4b54-9431-0eaf6446e2d6")] public static extern Win32Error EnumPrinterDataEx(HPRINTER hPrinter, string pKeyName, IntPtr pEnumValues, uint cbEnumValues, out uint pcbEnumValues, out uint pnEnumValues); /// /// The EnumPrinterDataEx function enumerates all value names and data for a specified printer and key. /// /// Printer data is stored in the registry. While enumerating printer data, do not call registry functions that might change the data. /// /// /// /// A handle to the printer for which the function retrieves configuration data. Use the OpenPrinter or AddPrinter /// function to retrieve a printer handle. /// /// /// /// A pointer to a null-terminated string that specifies the key containing the values to enumerate. Use the backslash ( \ ) /// character as a delimiter to specify a path with one or more subkeys. EnumPrinterDataEx enumerates all values of the key, /// but does not enumerate values of subkeys of the specified key. Use the EnumPrinterKey function to enumerate subkeys. /// /// If pKeyName is NULL or an empty string, EnumPrinterDataEx returns ERROR_INVALID_PARAMETER. /// /// /// A sequence of tuples, each with the following information. /// /// /// valueName ( ) /// The name of the configuration data value. /// /// /// valueType ( ) /// The type of data stored in the specified value. /// /// /// value ( ) /// The configuration data value. /// /// /// [PInvokeData("winspool.h", MSDNShortId = "bc5ecc46-24a4-4b54-9431-0eaf6446e2d6")] public static IEnumerable<(string valueName, REG_VALUE_TYPE valueType, object value)> EnumPrinterDataEx(HPRINTER hPrinter, string pKeyName = "PrinterDriverData") { EnumPrinterDataEx(hPrinter, pKeyName, default, 0, out var sz, out var cnt).ThrowUnless(Win32Error.ERROR_MORE_DATA); using var mem = new SafeCoTaskMemHandle(sz); EnumPrinterDataEx(hPrinter, pKeyName, mem, mem.Size, out sz, out cnt).ThrowIfFailed(); return mem.ToEnumerable((int)cnt).Select(v => (v.pValueName, v.dwType, v.dwType.GetValue(v.pData, v.cbData))).ToArray(); } /// /// The EnumPrinterKey function enumerates the subkeys of a specified key for a specified printer. /// /// Printer data is stored in the registry. While enumerating printer data, do not call registry functions that might change the data. /// /// /// /// A handle to the printer for which the function enumerates subkeys. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// /// /// A pointer to a null-terminated string that specifies the key containing the subkeys to enumerate. Use the backslash '\' /// character as a delimiter to specify a path with one or more subkeys. EnumPrinterKey enumerates all subkeys of the key, /// but does not enumerate the subkeys of those subkeys. /// /// /// If pKeyName is an empty string (""), EnumPrinterKey enumerates the top-level key for the printer. If pKeyName is /// NULL, EnumPrinterKey returns ERROR_INVALID_PARAMETER. /// /// /// /// A pointer to a buffer that receives an array of null-terminated subkey names. The array is terminated by two null characters. /// /// /// The size, in bytes, of the buffer pointed to by pSubkey. If you set cbSubkey to zero, the pcbSubkey parameter returns the /// required buffer size. /// /// /// A pointer to a variable that receives the number of bytes retrieved in the pSubkey buffer. If the buffer size specified by /// cbSubkey is too small, the function returns ERROR_MORE_DATA and pcbSubkey indicates the required buffer size. /// /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is a system error code. If pKeyName does not exist, the return value is ERROR_FILE_NOT_FOUND. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/enumprinterkey DWORD EnumPrinterKey( _In_ HANDLE hPrinter, _In_ LPCTSTR // pKeyName, _Out_ LPTSTR pSubkey, _In_ DWORD cbSubkey, _Out_ LPDWORD pcbSubkey ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "721b1d23-a594-4439-b8f9-9b11be5fe874")] public static extern Win32Error EnumPrinterKey(HPRINTER hPrinter, string pKeyName, IntPtr pSubkey, uint cbSubkey, out uint pcbSubkey); /// /// The EnumPrinterKey function enumerates the subkeys of a specified key for a specified printer. /// /// Printer data is stored in the registry. While enumerating printer data, do not call registry functions that might change the data. /// /// /// /// A handle to the printer for which the function enumerates subkeys. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// /// /// A pointer to a null-terminated string that specifies the key containing the subkeys to enumerate. Use the backslash '\' /// character as a delimiter to specify a path with one or more subkeys. EnumPrinterKey enumerates all subkeys of the key, /// but does not enumerate the subkeys of those subkeys. /// /// /// If pKeyName is an empty string (""), EnumPrinterKey enumerates the top-level key for the printer. If pKeyName is /// NULL, EnumPrinterKey returns ERROR_INVALID_PARAMETER. /// /// /// An array of subkey names. [PInvokeData("winspool.h", MSDNShortId = "721b1d23-a594-4439-b8f9-9b11be5fe874")] public static IEnumerable EnumPrinterKey(HPRINTER hPrinter, string pKeyName) { EnumPrinterKey(hPrinter, pKeyName, default, 0, out var bytes).ThrowUnless(Win32Error.ERROR_MORE_DATA); if (bytes == 0) return new string[0]; using var mem = new SafeCoTaskMemHandle(bytes); EnumPrinterKey(hPrinter, pKeyName, mem, mem.Size, out bytes).ThrowIfFailed(); return mem.ToStringEnum().ToArray(); } /// The EnumPrinters function enumerates available printers, print servers, domains, or print providers. /// /// The types of print objects that the function should enumerate. This value can be one or more of the following values. /// /// /// Value /// Meaning /// /// /// PRINTER_ENUM_LOCAL /// /// If the PRINTER_ENUM_NAME flag is not also passed, the function ignores the Name parameter, and enumerates the locally installed /// printers. If PRINTER_ENUM_NAME is also passed, the function enumerates the local printers on Name. /// /// /// /// PRINTER_ENUM_NAME /// /// The function enumerates the printer identified by Name. This can be a server, a domain, or a print provider. If Name is NULL, /// the function enumerates available print providers. /// /// /// /// PRINTER_ENUM_SHARED /// /// The function enumerates printers that have the shared attribute. Cannot be used in isolation; use an OR operation to combine /// with another PRINTER_ENUM type. /// /// /// /// PRINTER_ENUM_CONNECTIONS /// The function enumerates the list of printers to which the user has made previous connections. /// /// /// PRINTER_ENUM_NETWORK /// The function enumerates network printers in the computer's domain. This value is valid only if Level is 1. /// /// /// PRINTER_ENUM_REMOTE /// /// The function enumerates network printers and print servers in the computer's domain. This value is valid only if Level is 1. /// /// /// /// PRINTER_ENUM_CATEGORY_3D /// The function enumerates only 3D printers. /// /// /// PRINTER_ENUM_CATEGORY_ALL /// The function enumerates all print devices, including 3D printers. /// /// /// If Level is 4, you can only use the PRINTER_ENUM_CONNECTIONS and PRINTER_ENUM_LOCAL constants. /// /// /// /// If Level is 1, Flags contains PRINTER_ENUM_NAME, and Name is non- NULL, then Name is a pointer to a null-terminated /// string that specifies the name of the object to enumerate. This string can be the name of a server, a domain, or a print provider. /// /// /// If Level is 1, Flags contains PRINTER_ENUM_NAME, and Name is NULL, then the function enumerates the available print providers. /// /// /// If Level is 1, Flags contains PRINTER_ENUM_REMOTE, and Name is NULL, then the function enumerates the printers in the /// user's domain. /// /// /// If Level is 2 or 5,Name is a pointer to a null-terminated string that specifies the name of a server whose printers are to be /// enumerated. If this string is NULL, then the function enumerates the printers installed on the local computer. /// /// If Level is 4, Name should be NULL. The function always queries on the local computer. /// /// When Name is NULL, setting Flags to PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS enumerates printers that are installed /// on the local machine. These printers include those that are physically attached to the local machine as well as remote printers /// to which it has a network connection. /// /// /// When Name is not NULL, setting Flags to PRINTER_ENUM_LOCAL | PRINTER_ENUM_NAME enumerates the local printers that are /// installed on the server Name. /// /// /// /// /// The type of data structures pointed to by pPrinterEnum. Valid values are 1, 2, 4, and 5, which correspond to the /// PRINTER_INFO_1, PRINTER_INFO_2 , PRINTER_INFO_4, and PRINTER_INFO_5 data structures. /// /// This value can be 1, 2, 4, or 5. /// /// /// /// A pointer to a buffer that receives an array of PRINTER_INFO_1, PRINTER_INFO_2, PRINTER_INFO_4, or /// PRINTER_INFO_5 structures. Each structure contains data that describes an available print object. /// /// /// If Level is 1, the array contains PRINTER_INFO_1 structures. If Level is 2, the array contains PRINTER_INFO_2 /// structures. If Level is 4, the array contains PRINTER_INFO_4 structures. If Level is 5, the array contains /// PRINTER_INFO_5 structures. /// /// /// The buffer must be large enough to receive the array of data structures and any strings or other data to which the structure /// members point. If the buffer is too small, the pcbNeeded parameter returns the required buffer size. /// /// /// The size, in bytes, of the buffer pointed to by pPrinterEnum. /// /// A pointer to a value that receives the number of bytes copied if the function succeeds or the number of bytes required if cbBuf /// is too small. /// /// /// A pointer to a value that receives the number of PRINTER_INFO_1, PRINTER_INFO_2 , PRINTER_INFO_4, or /// PRINTER_INFO_5 structures that the function returns in the array to which pPrinterEnum points. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// Do not call this method in DllMain. /// /// If EnumPrinters returns a PRINTER_INFO_1 structure in which PRINTER_ENUM_CONTAINER is specified, this indicates /// that there is a hierarchy of printer objects. An application can enumerate the hierarchy by calling EnumPrinters again, /// setting Name to the value of the PRINTER_INFO_1 structure's pName member. /// /// /// The EnumPrinters function does not retrieve security information. If PRINTER_INFO_2 structures are returned in the /// array pointed to by pPrinterEnum, their pSecurityDescriptor members will be set to NULL. /// /// To get information about the default printer, call GetDefaultPrinter. /// /// The PRINTER_INFO_4 structure provides an easy and extremely fast way to retrieve the names of the printers installed on a /// local machine, as well as the remote connections that a user has established. When EnumPrinters is called with a /// PRINTER_INFO_4 data structure, that function queries the registry for the specified information, then returns /// immediately. This differs from the behavior of EnumPrinters when called with other levels of PRINTER_INFO_* data /// structures. In particular, when EnumPrinters is called with a level 2 ( PRINTER_INFO_2) data structure, it /// performs an OpenPrinter call on each remote connection. If a remote connection is down, or the remote server no longer /// exists, or the remote printer no longer exists, the function must wait for RPC to time out and consequently fail the /// OpenPrinter call. This can take a while. Passing a PRINTER_INFO_4 structure lets an application retrieve a bare /// minimum of required information; if more detailed information is desired, a subsequent EnumPrinters level 2 call can be made. /// /// /// Windows Vista: The printer data returned by EnumPrinters is retrieved from a local cache when the value of Level /// is 4. /// /// The following table shows the EnumPrinters output for various Flags values when the Level parameter is set to 1. /// /// In the Name parameter column of the table, you should substitute an appropriate name for Print Provider, Domain, and Machine. /// For example, for "Print Provider," you could use the name of the network print provider or the name of the local print provider. /// To retrieve print provider names, call EnumPrinters with Name set to NULL. /// /// /// /// Flags parameter /// Name parameter /// Result /// /// /// PRINTER_ENUM_LOCAL (and not PRINTER_ENUM_NAME) /// The Name parameter is ignored. /// All local printers. /// /// /// PRINTER_ENUM_NAME /// "Print Provider" /// All domain names /// /// /// PRINTER_ENUM_NAME /// "Print Provider!Domain" /// All printers and print servers in the computer's domain /// /// /// PRINTER_ENUM_NAME /// "Print Provider!!\\Machine" /// All printers shared at \\Machine /// /// /// PRINTER_ENUM_NAME /// An empty string, "" /// All local printers. /// /// /// PRINTER_ENUM_NAME /// NULL /// All print providers in the computer's domain /// /// /// PRINTER_ENUM_CONNECTIONS /// The Name parameter is ignored. /// All connected remote printers /// /// /// PRINTER_ENUM_NETWORK /// The Name parameter is ignored. /// All printers in the computer's domain /// /// /// PRINTER_ENUM_REMOTE /// An empty string, "" /// All printers and print servers in the computer's domain /// /// /// PRINTER_ENUM_REMOTE /// "Print Provider" /// Same as PRINTER_ENUM_NAME /// /// /// PRINTER_ENUM_REMOTE /// "Print Provider!Domain" /// All printers and print servers in computer's domain, regardless of Domain specified. /// /// /// PRINTER_ENUM_CATEGORY_3D /// The Name parameter is ignored. /// Only 3D printers are enumerated. /// /// /// PRINTER_ENUM_CATEGORY_ALL /// The Name parameter is ignored. /// 3D printers are enumerated, along with all other printers. /// /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/enumprinters BOOL EnumPrinters( _In_ DWORD Flags, _In_ LPTSTR Name, _In_ // DWORD Level, _Out_ LPBYTE pPrinterEnum, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded, _Out_ LPDWORD pcReturned ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "0d0cc726-c515-4146-9273-cdf1db3c76b7")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EnumPrinters(PRINTER_ENUM Flags, string Name, uint Level, IntPtr pPrinterEnum, uint cbBuf, out uint pcbNeeded, out uint pcReturned); /// The EnumPrinters function enumerates available printers, print servers, domains, or print providers. /// /// The type of form information to enumerate. This must be either , , /// , or . /// /// /// The types of print objects that the function should enumerate. This value can be one or more of the following values. /// /// /// Value /// Meaning /// /// /// PRINTER_ENUM_LOCAL /// /// If the PRINTER_ENUM_NAME flag is not also passed, the function ignores the Name parameter, and enumerates the locally installed /// printers. If PRINTER_ENUM_NAME is also passed, the function enumerates the local printers on Name. /// /// /// /// PRINTER_ENUM_NAME /// /// The function enumerates the printer identified by Name. This can be a server, a domain, or a print provider. If Name is NULL, /// the function enumerates available print providers. /// /// /// /// PRINTER_ENUM_SHARED /// /// The function enumerates printers that have the shared attribute. Cannot be used in isolation; use an OR operation to combine /// with another PRINTER_ENUM type. /// /// /// /// PRINTER_ENUM_CONNECTIONS /// The function enumerates the list of printers to which the user has made previous connections. /// /// /// PRINTER_ENUM_NETWORK /// The function enumerates network printers in the computer's domain. This value is valid only if Level is 1. /// /// /// PRINTER_ENUM_REMOTE /// /// The function enumerates network printers and print servers in the computer's domain. This value is valid only if Level is 1. /// /// /// /// PRINTER_ENUM_CATEGORY_3D /// The function enumerates only 3D printers. /// /// /// PRINTER_ENUM_CATEGORY_ALL /// The function enumerates all print devices, including 3D printers. /// /// /// If Level is 4, you can only use the PRINTER_ENUM_CONNECTIONS and PRINTER_ENUM_LOCAL constants. /// /// /// /// If Level is 1, Flags contains PRINTER_ENUM_NAME, and Name is non- NULL, then Name is a pointer to a null-terminated /// string that specifies the name of the object to enumerate. This string can be the name of a server, a domain, or a print provider. /// /// /// If Level is 1, Flags contains PRINTER_ENUM_NAME, and Name is NULL, then the function enumerates the available print providers. /// /// /// If Level is 1, Flags contains PRINTER_ENUM_REMOTE, and Name is NULL, then the function enumerates the printers in the /// user's domain. /// /// /// If Level is 2 or 5,Name is a pointer to a null-terminated string that specifies the name of a server whose printers are to be /// enumerated. If this string is NULL, then the function enumerates the printers installed on the local computer. /// /// If Level is 4, Name should be NULL. The function always queries on the local computer. /// /// When Name is NULL, setting Flags to PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS enumerates printers that are installed /// on the local machine. These printers include those that are physically attached to the local machine as well as remote printers /// to which it has a network connection. /// /// /// When Name is not NULL, setting Flags to PRINTER_ENUM_LOCAL | PRINTER_ENUM_NAME enumerates the local printers that are /// installed on the server Name. /// /// /// /// /// A sequence of the structures of . Each structure contains data that describes an available print object. /// /// [PInvokeData("winspool.h", MSDNShortId = "0d0cc726-c515-4146-9273-cdf1db3c76b7")] public static IEnumerable EnumPrinters(PRINTER_ENUM Flags = PRINTER_ENUM.PRINTER_ENUM_LOCAL, string Name = null) where T : struct { if (!TryGetLevel("PRINTER_INFO_", out var lvl)) throw new ArgumentException($"{nameof(EnumPrinters)} cannot process a structure of type {typeof(T).Name}."); if (!EnumPrinters(Flags, Name, lvl, default, 0, out var bytes, out var count)) Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_INSUFFICIENT_BUFFER); if (bytes == 0) return new T[0]; using var mem = new SafeCoTaskMemHandle(bytes); if (!EnumPrinters(Flags, Name, lvl, mem, mem.Size, out bytes, out count)) Win32Error.ThrowLastError(); return mem.ToArray((int)count); } /// /// The FindClosePrinterChangeNotification function closes a change notification object created by calling the /// FindFirstPrinterChangeNotification function. The printer or print server associated with the change notification object /// will no longer be monitored by that object. /// /// /// A handle to the change notification object to be closed. This is a handle created by calling the /// FindFirstPrinterChangeNotification function. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// After calling the FindClosePrinterChangeNotification function, you cannot use the hChange handle in subsequent calls to /// either FindFirstPrinterChangeNotification or FindNextPrinterChangeNotification. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/findcloseprinterchangenotification BOOL // FindClosePrinterChangeNotification( _In_ HANDLE hChange ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "2b4758f8-af0a-494b-8f1b-8ea6ee73c79b")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FindClosePrinterChangeNotification(HPRINTERCHANGENOTIFICATION hChange); /// /// /// The FindFirstPrinterChangeNotification function creates a change notification object and returns a handle to the object. /// You can then use this handle in a call to one of the wait functions to monitor changes to the printer or print server. /// /// /// The FindFirstPrinterChangeNotification call specifies the type of changes to be monitored. You can specify a set of /// conditions to monitor for changes, a set of printer information fields to monitor, or both. /// /// /// A wait operation on the change notification handle succeeds when one of the specified changes occurs in the specified printer or /// print server. You then call the FindNextPrinterChangeNotification function to retrieve information about the change, and /// to reset the change notification object for use in the next wait operation. /// /// /// /// A handle to the printer or print server that you want to monitor. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// /// /// The conditions that will cause the change notification object to enter a signaled state. A change notification occurs when one /// or more of the specified conditions are met. The fdwFilter parameter can be zero if pPrinterNotifyOptions is non- NULL. /// /// This parameter can be one or more of the following values. /// /// /// Value /// Meaning /// /// /// PRINTER_CHANGE_FORM /// /// Notify of any changes to a form. You can set this general flag or one or more of the following specific flags: /// PRINTER_CHANGE_ADD_FORM PRINTER_CHANGE_SET_FORM PRINTER_CHANGE_DELETE_FORM /// /// /// /// PRINTER_CHANGE_JOB /// /// Notify of any changes to a job. You can set this general flag or one or more of the following specific flags: /// PRINTER_CHANGE_ADD_JOB PRINTER_CHANGE_SET_JOB PRINTER_CHANGE_DELETE_JOB PRINTER_CHANGE_WRITE_JOB /// /// /// /// PRINTER_CHANGE_PORT /// /// Notify of any changes to a port. You can set this general flag or one or more of the following specific flags: /// PRINTER_CHANGE_ADD_PORT PRINTER_CHANGE_CONFIGURE_PORT PRINTER_CHANGE_DELETE_PORT /// /// /// /// PRINTER_CHANGE_PRINT_PROCESSOR /// /// Notify of any changes to a print processor. You can set this general flag or one or more of the following specific flags: /// PRINTER_CHANGE_ADD_PRINT_PROCESSOR PRINTER_CHANGE_DELETE_PRINT_PROCESSOR /// /// /// /// PRINTER_CHANGE_PRINTER /// /// Notify of any changes to a printer. You can set this general flag or one or more of the following specific flags: /// PRINTER_CHANGE_ADD_PRINTER PRINTER_CHANGE_SET_PRINTER PRINTER_CHANGE_DELETE_PRINTER PRINTER_CHANGE_FAILED_CONNECTION_PRINTER /// /// /// /// PRINTER_CHANGE_PRINTER_DRIVER /// /// Notify of any changes to a printer driver. You can set this general flag or one or more of the following specific flags: /// PRINTER_CHANGE_ADD_PRINTER_DRIVER PRINTER_CHANGE_SET_PRINTER_DRIVER PRINTER_CHANGE_DELETE_PRINTER_DRIVER /// /// /// /// PRINTER_CHANGE_ALL /// Notify if any of the preceding changes occur. /// /// /// PRINTER_CHANGE_SERVER /// /// Windows 7: Notify of any changes to the server. This flag is not included in the changes monitored by setting the /// PRINTER_CHANGE_ALL value. /// /// /// /// For descriptions of the more specific flags in the preceding table, see the FindNextPrinterChangeNotification function. /// /// /// The flag that determines the category of printers for which notifications will work. /// /// /// Value /// Meaning /// /// /// PRINTER_NOTIFY_CATEGORY_ALL 0x001000 /// FindNextPrinterChangeNotification returns notifications for both 2D and 3D printers. /// /// /// PRINTER_NOTIFY_CATEGORY_3D 0x002000 /// FindNextPrinterChangeNotification returns notifications only for 3D printers. /// /// /// /// When this flag is set to zero (0), FindFirstPrinterChangeNotification will only work for 2D printers. This is the default value. /// /// /// /// /// A pointer to a PRINTER_NOTIFY_OPTIONS structure. The pTypes member of this structure is an array of one or more /// PRINTER_NOTIFY_OPTIONS_TYPE structures, each of which specifies a printer information field to monitor. A change /// notification occurs when one or more of the specified fields changes. When a change occurs, the /// FindNextPrinterChangeNotification function can retrieve the new printer information. This parameter can be NULL if /// fdwFilter is nonzero. /// /// For a list of fields that can be monitored, see PRINTER_NOTIFY_OPTIONS_TYPE. /// /// /// /// If the function succeeds, the return value is a handle to a change notification object associated with the specified printer or /// print server. /// /// If the function fails, the return value is INVALID_HANDLE_VALUE. /// /// /// /// To monitor a printer or print server, call the FindFirstPrinterChangeNotification function, then use the returned change /// notification object handle in a call to one of the wait functions. A wait operation on a change notification object is satisfied /// when the change notification object enters the signaled state. The system signals the object when one or more of the changes /// specified by fdwFilter or pPrinterNotifyOptions occurs in the monitored printer or print server. /// /// /// When you call FindFirstPrinterChangeNotification, either fdwFilter must be nonzero or pPrinterNotifyOptions must be non- /// NULL. If both are specified, notifications will occur for both. /// /// /// When a wait operation on a printer change notification object is satisfied, call the FindNextPrinterChangeNotification /// function to determine the cause of the notification. For a condition specified by fdwFilter, /// FindNextPrinterChangeNotification reports the condition or conditions that changed. For a printer information field /// specified by pPrinterNotifyOptions, FindNextPrinterChangeNotification reports the field or fields that changed as well as /// the new information for these fields. FindNextPrinterChangeNotification also resets the change notification object to the /// nonsignaled state so you can use it in another wait operation to continue monitoring the printer or print server. /// /// /// With one exception, do not call the FindNextPrinterChangeNotification function if the change notification object is not /// in the signaled state. If the wait function returns the value WAIT_TIMEOUT, the change object is not in the signaled state. Call /// the FindNextPrinterChangeNotification function only if the wait function succeeds without timing out. The exception is /// when FindNextPrinterChangeNotification is called with the PRINTER_NOTIFY_OPTIONS_REFRESH bit set in the /// pPrinterNotifyOptions parameter. /// /// /// When you no longer need the change notification object, close it by calling the FindClosePrinterChangeNotification function. /// /// /// Callers of FindFirstPrinterChangeNotification must ensure that the printer handle passed into /// FindFirstPrinterChangeNotification remains valid until FindClosePrinterChangeNotification is called. If the /// printer handle is closed before the printer change notification handle, further notifications will fail to be delivered. /// /// FindFirstPrinterChangeNotification will not send change notifications for 3D printers to server handles. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/findfirstprinterchangenotification HANDLE // FindFirstPrinterChangeNotification( _In_ HANDLE hPrinter, DWORD fdwFilter, DWORD fdwOptions, _In_opt_ LPVOID // pPrinterNotifyOptions ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "4155ef5c-cd96-4960-919b-d9a495bb73a5")] public static extern SafeHPRINTERCHANGENOTIFICATION FindFirstPrinterChangeNotification(HPRINTER hPrinter, PRINTER_CHANGE fdwFilter, PRINTER_NOTIFY_CATEGORY fdwOptions, in PRINTER_NOTIFY_OPTIONS pPrinterNotifyOptions); /// /// /// The FindFirstPrinterChangeNotification function creates a change notification object and returns a handle to the object. /// You can then use this handle in a call to one of the wait functions to monitor changes to the printer or print server. /// /// /// The FindFirstPrinterChangeNotification call specifies the type of changes to be monitored. You can specify a set of /// conditions to monitor for changes, a set of printer information fields to monitor, or both. /// /// /// A wait operation on the change notification handle succeeds when one of the specified changes occurs in the specified printer or /// print server. You then call the FindNextPrinterChangeNotification function to retrieve information about the change, and /// to reset the change notification object for use in the next wait operation. /// /// /// /// A handle to the printer or print server that you want to monitor. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// /// /// The conditions that will cause the change notification object to enter a signaled state. A change notification occurs when one /// or more of the specified conditions are met. The fdwFilter parameter can be zero if pPrinterNotifyOptions is non- NULL. /// /// This parameter can be one or more of the following values. /// /// /// Value /// Meaning /// /// /// PRINTER_CHANGE_FORM /// /// Notify of any changes to a form. You can set this general flag or one or more of the following specific flags: /// PRINTER_CHANGE_ADD_FORM PRINTER_CHANGE_SET_FORM PRINTER_CHANGE_DELETE_FORM /// /// /// /// PRINTER_CHANGE_JOB /// /// Notify of any changes to a job. You can set this general flag or one or more of the following specific flags: /// PRINTER_CHANGE_ADD_JOB PRINTER_CHANGE_SET_JOB PRINTER_CHANGE_DELETE_JOB PRINTER_CHANGE_WRITE_JOB /// /// /// /// PRINTER_CHANGE_PORT /// /// Notify of any changes to a port. You can set this general flag or one or more of the following specific flags: /// PRINTER_CHANGE_ADD_PORT PRINTER_CHANGE_CONFIGURE_PORT PRINTER_CHANGE_DELETE_PORT /// /// /// /// PRINTER_CHANGE_PRINT_PROCESSOR /// /// Notify of any changes to a print processor. You can set this general flag or one or more of the following specific flags: /// PRINTER_CHANGE_ADD_PRINT_PROCESSOR PRINTER_CHANGE_DELETE_PRINT_PROCESSOR /// /// /// /// PRINTER_CHANGE_PRINTER /// /// Notify of any changes to a printer. You can set this general flag or one or more of the following specific flags: /// PRINTER_CHANGE_ADD_PRINTER PRINTER_CHANGE_SET_PRINTER PRINTER_CHANGE_DELETE_PRINTER PRINTER_CHANGE_FAILED_CONNECTION_PRINTER /// /// /// /// PRINTER_CHANGE_PRINTER_DRIVER /// /// Notify of any changes to a printer driver. You can set this general flag or one or more of the following specific flags: /// PRINTER_CHANGE_ADD_PRINTER_DRIVER PRINTER_CHANGE_SET_PRINTER_DRIVER PRINTER_CHANGE_DELETE_PRINTER_DRIVER /// /// /// /// PRINTER_CHANGE_ALL /// Notify if any of the preceding changes occur. /// /// /// PRINTER_CHANGE_SERVER /// /// Windows 7: Notify of any changes to the server. This flag is not included in the changes monitored by setting the /// PRINTER_CHANGE_ALL value. /// /// /// /// For descriptions of the more specific flags in the preceding table, see the FindNextPrinterChangeNotification function. /// /// /// The flag that determines the category of printers for which notifications will work. /// /// /// Value /// Meaning /// /// /// PRINTER_NOTIFY_CATEGORY_ALL 0x001000 /// FindNextPrinterChangeNotification returns notifications for both 2D and 3D printers. /// /// /// PRINTER_NOTIFY_CATEGORY_3D 0x002000 /// FindNextPrinterChangeNotification returns notifications only for 3D printers. /// /// /// /// When this flag is set to zero (0), FindFirstPrinterChangeNotification will only work for 2D printers. This is the default value. /// /// /// /// /// A pointer to a PRINTER_NOTIFY_OPTIONS structure. The pTypes member of this structure is an array of one or more /// PRINTER_NOTIFY_OPTIONS_TYPE structures, each of which specifies a printer information field to monitor. A change /// notification occurs when one or more of the specified fields changes. When a change occurs, the /// FindNextPrinterChangeNotification function can retrieve the new printer information. This parameter can be NULL if /// fdwFilter is nonzero. /// /// For a list of fields that can be monitored, see PRINTER_NOTIFY_OPTIONS_TYPE. /// /// /// /// If the function succeeds, the return value is a handle to a change notification object associated with the specified printer or /// print server. /// /// If the function fails, the return value is INVALID_HANDLE_VALUE. /// /// /// /// To monitor a printer or print server, call the FindFirstPrinterChangeNotification function, then use the returned change /// notification object handle in a call to one of the wait functions. A wait operation on a change notification object is satisfied /// when the change notification object enters the signaled state. The system signals the object when one or more of the changes /// specified by fdwFilter or pPrinterNotifyOptions occurs in the monitored printer or print server. /// /// /// When you call FindFirstPrinterChangeNotification, either fdwFilter must be nonzero or pPrinterNotifyOptions must be non- /// NULL. If both are specified, notifications will occur for both. /// /// /// When a wait operation on a printer change notification object is satisfied, call the FindNextPrinterChangeNotification /// function to determine the cause of the notification. For a condition specified by fdwFilter, /// FindNextPrinterChangeNotification reports the condition or conditions that changed. For a printer information field /// specified by pPrinterNotifyOptions, FindNextPrinterChangeNotification reports the field or fields that changed as well as /// the new information for these fields. FindNextPrinterChangeNotification also resets the change notification object to the /// nonsignaled state so you can use it in another wait operation to continue monitoring the printer or print server. /// /// /// With one exception, do not call the FindNextPrinterChangeNotification function if the change notification object is not /// in the signaled state. If the wait function returns the value WAIT_TIMEOUT, the change object is not in the signaled state. Call /// the FindNextPrinterChangeNotification function only if the wait function succeeds without timing out. The exception is /// when FindNextPrinterChangeNotification is called with the PRINTER_NOTIFY_OPTIONS_REFRESH bit set in the /// pPrinterNotifyOptions parameter. /// /// /// When you no longer need the change notification object, close it by calling the FindClosePrinterChangeNotification function. /// /// /// Callers of FindFirstPrinterChangeNotification must ensure that the printer handle passed into /// FindFirstPrinterChangeNotification remains valid until FindClosePrinterChangeNotification is called. If the /// printer handle is closed before the printer change notification handle, further notifications will fail to be delivered. /// /// FindFirstPrinterChangeNotification will not send change notifications for 3D printers to server handles. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/findfirstprinterchangenotification HANDLE // FindFirstPrinterChangeNotification( _In_ HANDLE hPrinter, DWORD fdwFilter, DWORD fdwOptions, _In_opt_ LPVOID // pPrinterNotifyOptions ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "4155ef5c-cd96-4960-919b-d9a495bb73a5")] public static extern SafeHPRINTERCHANGENOTIFICATION FindFirstPrinterChangeNotification(HPRINTER hPrinter, PRINTER_CHANGE fdwFilter, PRINTER_NOTIFY_CATEGORY fdwOptions, [In, Optional] IntPtr pPrinterNotifyOptions); /// /// /// The FindNextPrinterChangeNotification function retrieves information about the most recent change notification for a /// change notification object associated with a printer or print server. Call this function when a wait operation on the change /// notification object is satisfied. /// /// /// The function also resets the change notification object to the not-signaled state. You can then use the object in another wait /// operation to continue monitoring the printer or print server. The operating system will set the object to the signaled state the /// next time one of a specified set of changes occurs to the printer or print server. The FindFirstPrinterChangeNotification /// function creates the change notification object and specifies the set of changes to be monitored. /// /// /// /// A handle to a change notification object associated with a printer or print server. You obtain such a handle by calling the /// FindFirstPrinterChangeNotification function. The operating system sets this change notification object to the signaled /// state when it detects one of the changes specified in the object's change notification filter. /// /// /// /// A pointer to a variable whose bits are set to indicate the changes that occurred to cause the most recent notification. The bit /// flags that might be set correspond to those specified in the fdwFilter parameter of the /// FindFirstPrinterChangeNotification call. The system sets one or more of the following bit flags. /// /// /// /// Value /// Meaning /// /// /// PRINTER_CHANGE_ADD_FORM /// A form was added to the server. /// /// /// PRINTER_CHANGE_ADD_JOB /// A print job was sent to the printer. /// /// /// PRINTER_CHANGE_ADD_PORT /// A port or monitor was added to the server. /// /// /// PRINTER_CHANGE_ADD_PRINT_PROCESSOR /// A print processor was added to the server. /// /// /// PRINTER_CHANGE_ADD_PRINTER /// A printer was added to the server. /// /// /// PRINTER_CHANGE_ADD_PRINTER_DRIVER /// A printer driver was added to the server. /// /// /// PRINTER_CHANGE_CONFIGURE_PORT /// A port was configured on the server. /// /// /// PRINTER_CHANGE_DELETE_FORM /// A form was deleted from the server. /// /// /// PRINTER_CHANGE_DELETE_JOB /// A job was deleted. /// /// /// PRINTER_CHANGE_DELETE_PORT /// A port or monitor was deleted from the server. /// /// /// PRINTER_CHANGE_DELETE_PRINT_PROCESSOR /// A print processor was deleted from the server. /// /// /// PRINTER_CHANGE_DELETE_PRINTER /// A printer was deleted. /// /// /// PRINTER_CHANGE_DELETE_PRINTER_DRIVER /// A printer driver was deleted from the server. /// /// /// PRINTER_CHANGE_FAILED_CONNECTION_PRINTER /// A printer connection has failed. /// /// /// PRINTER_CHANGE_SET_FORM /// A form was set on the server. /// /// /// PRINTER_CHANGE_SET_JOB /// A job was set. /// /// /// PRINTER_CHANGE_SET_PRINTER /// A printer was set. /// /// /// PRINTER_CHANGE_SET_PRINTER_DRIVER /// A printer driver was set. /// /// /// PRINTER_CHANGE_WRITE_JOB /// Job data was written. /// /// /// PRINTER_CHANGE_TIMEOUT /// The job timed out. /// /// /// PRINTER_CHANGE_SERVER /// Windows 7: A change occurred on the server. /// /// /// /// /// A pointer to a PRINTER_NOTIFY_OPTIONS structure. Set the Flags member of this structure to /// PRINTER_NOTIFY_OPTIONS_REFRESH, to cause the function to return the current data for all monitored printer information /// fields. The function ignores all other members of the structure. This parameter can be NULL. /// /// /// /// A pointer to a pointer variable that receives a pointer to a system-allocated, read-only buffer. Call the /// FreePrinterNotifyInfo function to free the buffer when you are finished with it. This parameter can be NULL if no /// information is required. /// /// /// The buffer contains a PRINTER_NOTIFY_INFO structure, which contains an array of PRINTER_NOTIFY_INFO_DATA /// structures. Each element of the array contains information about one of the fields specified in the pPrinterNotifyOptions /// parameter of the FindFirstPrinterChangeNotification call. Typically, the function provides data only for the fields that /// changed to cause the most recent notification. However, if the structure pointed to by the pPrinterNotifyOptions parameter /// specifies PRINTER_NOTIFY_OPTIONS_REFRESH, the function provides data for all monitored fields. /// /// /// If the PRINTER_NOTIFY_INFO_DISCARDED bit is set in the Flags member of the PRINTER_NOTIFY_INFO structure, /// an overflow or error occurred, and notifications may have been lost. In this case, no additional notifications will be sent /// until you make a second FindNextPrinterChangeNotification call that specifies PRINTER_NOTIFY_OPTIONS_REFRESH. /// /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// Call the FindNextPrinterChangeNotification function after a wait operation on a notification object created by /// FindFirstPrinterChangeNotification has been satisfied. Calling FindNextPrinterChangeNotification lets you obtain /// information about the change that satisfied the wait operation, and resets the notification object so it can be signaled when /// the next change occurs. /// /// /// With one exception, do not call the FindNextPrinterChangeNotification function if the change notification object is not /// in the signaled state. If a wait function returns the value WAIT_TIMEOUT, the change object is not in the signaled state. /// Call the FindNextPrinterChangeNotification function only if the wait function succeeds without timing out. The exception /// is when FindNextPrinterChangeNotification is called with the PRINTER_NOTIFY_OPTIONS_REFRESH bit set in the /// pPrinterNotifyOptions parameter. Note that even when this flag is set, it is still possible for the /// PRINTER_NOTIFY_INFO_DISCARDED flag to be set in the ppPrinterNotifyInfo parameter. /// /// /// To continue monitoring the printer or print server for changes, repeat the cycle of calling one of the wait functions , and then /// calling the FindNextPrinterChangeNotification function to examine the change and reset the notification object. /// /// /// FindNextPrinterChangeNotification may combine multiple changes to the same printer information field into a single /// notification. When this occurs, the function typically collapses all changes for the field into a single entry in the array of /// PRINTER_NOTIFY_INFO_DATA structures in ppPrinterNotifyInfo; the single entry reports only the most current information. /// However, for some job and printer information fields, the function can return multiple array entries for the same field. In this /// case, the last array entry for the field reports the current data, and the earlier entries contain the data for the intermediate stages. /// /// /// When you no longer need the change notification object, close it by calling the FindClosePrinterChangeNotification function. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/findnextprinterchangenotification BOOL // FindNextPrinterChangeNotification( _In_ HANDLE hChange, _Out_opt_ PDWORD pdwChange, _In_opt_ LPVOID pPrinterNotifyOptions, // _Out_opt_ LPVOID *ppPrinterNotifyInfo ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "ea7774ae-361f-41e4-bbc6-3f100028b22a")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FindNextPrinterChangeNotification(HPRINTERCHANGENOTIFICATION hChange, out PRINTER_CHANGE pdwChange, in PRINTER_NOTIFY_OPTIONS pPrinterNotifyOptions, out SafePRINTER_NOTIFY_INFO ppPrinterNotifyInfo); /// /// /// The FindNextPrinterChangeNotification function retrieves information about the most recent change notification for a /// change notification object associated with a printer or print server. Call this function when a wait operation on the change /// notification object is satisfied. /// /// /// The function also resets the change notification object to the not-signaled state. You can then use the object in another wait /// operation to continue monitoring the printer or print server. The operating system will set the object to the signaled state the /// next time one of a specified set of changes occurs to the printer or print server. The FindFirstPrinterChangeNotification /// function creates the change notification object and specifies the set of changes to be monitored. /// /// /// /// A handle to a change notification object associated with a printer or print server. You obtain such a handle by calling the /// FindFirstPrinterChangeNotification function. The operating system sets this change notification object to the signaled /// state when it detects one of the changes specified in the object's change notification filter. /// /// /// /// A pointer to a variable whose bits are set to indicate the changes that occurred to cause the most recent notification. The bit /// flags that might be set correspond to those specified in the fdwFilter parameter of the /// FindFirstPrinterChangeNotification call. The system sets one or more of the following bit flags. /// /// /// /// Value /// Meaning /// /// /// PRINTER_CHANGE_ADD_FORM /// A form was added to the server. /// /// /// PRINTER_CHANGE_ADD_JOB /// A print job was sent to the printer. /// /// /// PRINTER_CHANGE_ADD_PORT /// A port or monitor was added to the server. /// /// /// PRINTER_CHANGE_ADD_PRINT_PROCESSOR /// A print processor was added to the server. /// /// /// PRINTER_CHANGE_ADD_PRINTER /// A printer was added to the server. /// /// /// PRINTER_CHANGE_ADD_PRINTER_DRIVER /// A printer driver was added to the server. /// /// /// PRINTER_CHANGE_CONFIGURE_PORT /// A port was configured on the server. /// /// /// PRINTER_CHANGE_DELETE_FORM /// A form was deleted from the server. /// /// /// PRINTER_CHANGE_DELETE_JOB /// A job was deleted. /// /// /// PRINTER_CHANGE_DELETE_PORT /// A port or monitor was deleted from the server. /// /// /// PRINTER_CHANGE_DELETE_PRINT_PROCESSOR /// A print processor was deleted from the server. /// /// /// PRINTER_CHANGE_DELETE_PRINTER /// A printer was deleted. /// /// /// PRINTER_CHANGE_DELETE_PRINTER_DRIVER /// A printer driver was deleted from the server. /// /// /// PRINTER_CHANGE_FAILED_CONNECTION_PRINTER /// A printer connection has failed. /// /// /// PRINTER_CHANGE_SET_FORM /// A form was set on the server. /// /// /// PRINTER_CHANGE_SET_JOB /// A job was set. /// /// /// PRINTER_CHANGE_SET_PRINTER /// A printer was set. /// /// /// PRINTER_CHANGE_SET_PRINTER_DRIVER /// A printer driver was set. /// /// /// PRINTER_CHANGE_WRITE_JOB /// Job data was written. /// /// /// PRINTER_CHANGE_TIMEOUT /// The job timed out. /// /// /// PRINTER_CHANGE_SERVER /// Windows 7: A change occurred on the server. /// /// /// /// /// A pointer to a PRINTER_NOTIFY_OPTIONS structure. Set the Flags member of this structure to /// PRINTER_NOTIFY_OPTIONS_REFRESH, to cause the function to return the current data for all monitored printer information /// fields. The function ignores all other members of the structure. This parameter can be NULL. /// /// /// /// A pointer to a pointer variable that receives a pointer to a system-allocated, read-only buffer. Call the /// FreePrinterNotifyInfo function to free the buffer when you are finished with it. This parameter can be NULL if no /// information is required. /// /// /// The buffer contains a PRINTER_NOTIFY_INFO structure, which contains an array of PRINTER_NOTIFY_INFO_DATA /// structures. Each element of the array contains information about one of the fields specified in the pPrinterNotifyOptions /// parameter of the FindFirstPrinterChangeNotification call. Typically, the function provides data only for the fields that /// changed to cause the most recent notification. However, if the structure pointed to by the pPrinterNotifyOptions parameter /// specifies PRINTER_NOTIFY_OPTIONS_REFRESH, the function provides data for all monitored fields. /// /// /// If the PRINTER_NOTIFY_INFO_DISCARDED bit is set in the Flags member of the PRINTER_NOTIFY_INFO structure, /// an overflow or error occurred, and notifications may have been lost. In this case, no additional notifications will be sent /// until you make a second FindNextPrinterChangeNotification call that specifies PRINTER_NOTIFY_OPTIONS_REFRESH. /// /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// Call the FindNextPrinterChangeNotification function after a wait operation on a notification object created by /// FindFirstPrinterChangeNotification has been satisfied. Calling FindNextPrinterChangeNotification lets you obtain /// information about the change that satisfied the wait operation, and resets the notification object so it can be signaled when /// the next change occurs. /// /// /// With one exception, do not call the FindNextPrinterChangeNotification function if the change notification object is not /// in the signaled state. If a wait function returns the value WAIT_TIMEOUT, the change object is not in the signaled state. /// Call the FindNextPrinterChangeNotification function only if the wait function succeeds without timing out. The exception /// is when FindNextPrinterChangeNotification is called with the PRINTER_NOTIFY_OPTIONS_REFRESH bit set in the /// pPrinterNotifyOptions parameter. Note that even when this flag is set, it is still possible for the /// PRINTER_NOTIFY_INFO_DISCARDED flag to be set in the ppPrinterNotifyInfo parameter. /// /// /// To continue monitoring the printer or print server for changes, repeat the cycle of calling one of the wait functions , and then /// calling the FindNextPrinterChangeNotification function to examine the change and reset the notification object. /// /// /// FindNextPrinterChangeNotification may combine multiple changes to the same printer information field into a single /// notification. When this occurs, the function typically collapses all changes for the field into a single entry in the array of /// PRINTER_NOTIFY_INFO_DATA structures in ppPrinterNotifyInfo; the single entry reports only the most current information. /// However, for some job and printer information fields, the function can return multiple array entries for the same field. In this /// case, the last array entry for the field reports the current data, and the earlier entries contain the data for the intermediate stages. /// /// /// When you no longer need the change notification object, close it by calling the FindClosePrinterChangeNotification function. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/findnextprinterchangenotification BOOL // FindNextPrinterChangeNotification( _In_ HANDLE hChange, _Out_opt_ PDWORD pdwChange, _In_opt_ LPVOID pPrinterNotifyOptions, // _Out_opt_ LPVOID *ppPrinterNotifyInfo ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "ea7774ae-361f-41e4-bbc6-3f100028b22a")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FindNextPrinterChangeNotification(HPRINTERCHANGENOTIFICATION hChange, out PRINTER_CHANGE pdwChange, [Optional] IntPtr pPrinterNotifyOptions, out SafePRINTER_NOTIFY_INFO ppPrinterNotifyInfo); /// The FlushPrinter function sends a buffer to the printer in order to clear it from a transient state. /// /// A handle to the printer object. This should be the same handle that was used, in a prior WritePrinter call, by the /// printer driver. /// /// A pointer to an array of bytes that contains the data to be written to the printer. /// The size, in bytes, of the array pointed to by pBuf. /// A pointer to a value that receives the number of bytes of data that were written to the printer. /// The time, in milliseconds, for which the I/O line to the printer port should be kept idle. /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. /// /// /// /// FlushPrinter should be called only if WritePrinter failed, leaving the printer in a transient state. For example, /// the printer could get into a transient state when the job gets aborted and the printer driver has partially sent some raw data /// to the printer. /// /// /// FlushPrinter also can specify an idle period during which the print spooler does not schedule any jobs to the /// corresponding printer port. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/flushprinter BOOL FlushPrinter( _In_ HANDLE hPrinter, _In_ LPVOID pBuf, // _In_ DWORD cbBuf, _Out_ LPDWORD pcWritten, _In_ DWORD cSleep ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "08e54175-da68-4ebd-91ec-8f4525f49d30")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FlushPrinter(HPRINTER hPrinter, IntPtr pBuf, uint cbBuf, out uint pcWritten, uint cSleep); /// The FlushPrinter function sends a buffer to the printer in order to clear it from a transient state. /// /// A handle to the printer object. This should be the same handle that was used, in a prior WritePrinter call, by the /// printer driver. /// /// A pointer to an array of bytes that contains the data to be written to the printer. /// The size, in bytes, of the array pointed to by pBuf. /// A pointer to a value that receives the number of bytes of data that were written to the printer. /// The time, in milliseconds, for which the I/O line to the printer port should be kept idle. /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. /// /// /// /// FlushPrinter should be called only if WritePrinter failed, leaving the printer in a transient state. For example, /// the printer could get into a transient state when the job gets aborted and the printer driver has partially sent some raw data /// to the printer. /// /// /// FlushPrinter also can specify an idle period during which the print spooler does not schedule any jobs to the /// corresponding printer port. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/flushprinter BOOL FlushPrinter( _In_ HANDLE hPrinter, _In_ LPVOID pBuf, // _In_ DWORD cbBuf, _Out_ LPDWORD pcWritten, _In_ DWORD cSleep ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "08e54175-da68-4ebd-91ec-8f4525f49d30")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FlushPrinter(HPRINTER hPrinter, byte[] pBuf, int cbBuf, out uint pcWritten, uint cSleep); /// /// The FreePrinterNotifyInfo function frees a system-allocated buffer created by the /// FindNextPrinterChangeNotification function. /// /// /// Pointer to a PRINTER_NOTIFY_INFO buffer returned from a call to the FindNextPrinterChangeNotification function. /// FreePrinterNotifyInfo deallocates this buffer. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/freeprinternotifyinfo BOOL FreePrinterNotifyInfo( _In_ // PPRINTER_NOTIFY_INFO pPrinterNotifyInfo ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "e50d4718-3682-486b-9d07-ddddd0b284dc")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FreePrinterNotifyInfo(IntPtr pPrinterNotifyInfo); /// /// The GetDefaultPrinter function retrieves the printer name of the default printer for the current user on the local computer. /// /// /// A pointer to a buffer that receives a null-terminated character string containing the default printer name. If this parameter is /// NULL, the function fails and the variable pointed to by pcchBuffer returns the required buffer size, in characters. /// /// /// On input, specifies the size, in characters, of the pszBuffer buffer. On output, receives the size, in characters, of the /// printer name string, including the terminating null character. /// /// /// /// If the function succeeds, the return value is a nonzero value and the variable pointed to by pcchBuffer contains the number of /// characters copied to the pszBuffer buffer, including the terminating null character. /// /// If the function fails, the return value is zero. /// /// /// Value /// Meaning /// /// /// ERROR_INSUFFICIENT_BUFFER /// The pszBuffer buffer is too small. The variable pointed to by pcchBuffer contains the required buffer size, in characters. /// /// /// ERROR_FILE_NOT_FOUND /// There is no default printer. /// /// /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/getdefaultprinter BOOL GetDefaultPrinter( _In_ LPTSTR pszBuffer, _Inout_ // LPDWORD pcchBuffer ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "8ec06743-43ce-4fac-83c4-f09eac7ee333")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetDefaultPrinter(StringBuilder pszBuffer, ref int pcchBuffer); /// The GetForm function retrieves information about a specified form. /// /// A handle to the printer. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// /// A pointer to a null-terminated string that specifies the name of the form. To get the names of the forms supported by the /// printer, call the EnumForms function. /// /// The version of the structure to which pForm points. This value must be 1 or 2. /// A pointer to an array of bytes that receives the initialized FORM_INFO_1 or FORM_INFO_2 structure. /// The size, in bytes, of the pForm array. /// /// A pointer to a value that specifies the number of bytes copied if the function succeeds or the number of bytes required if cbBuf /// is too small. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// If the caller is remote, and the Level is 2, the StringType value of the returned FORM_INFO_2 will always be STRING_LANGPAIR. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/getform BOOL GetForm( _In_ HANDLE hPrinter, _In_ LPTSTR pFormName, _In_ // DWORD Level, _Out_ LPBYTE pForm, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "10b25748-6d7c-46ab-bd2c-9b6126a1d7d1")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetForm(HPRINTER hPrinter, string pFormName, uint Level, IntPtr pForm, uint cbBuf, out uint pcbNeeded); /// The GetForm function retrieves information about a specified form. /// The type of the structure to get. This must be either FORM_INFO_1 or FORM_INFO_2. /// /// A handle to the printer. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// /// A pointer to a null-terminated string that specifies the name of the form. To get the names of the forms supported by the /// printer, call the EnumForms function. /// /// The initialized FORM_INFO_1 or FORM_INFO_2 structure. /// /// /// If the caller is remote, and the Level is 2, the StringType value of the returned FORM_INFO_2 will always be STRING_LANGPAIR. /// [PInvokeData("winspool.h", MSDNShortId = "10b25748-6d7c-46ab-bd2c-9b6126a1d7d1")] public static T GetForm(HPRINTER hPrinter, string pFormName) where T : struct { if (!TryGetLevel("FORM_INFO_", out var lvl)) throw new ArgumentException($"{nameof(GetForm)} cannot process a structure of type {typeof(T).Name}."); if (!GetForm(hPrinter, pFormName, lvl, default, 0, out var sz)) Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_INSUFFICIENT_BUFFER); using var mem = new SafeCoTaskMemHandle(sz); if (!GetForm(hPrinter, pFormName, lvl, mem, mem.Size, out sz)) Win32Error.ThrowLastError(); return mem.ToStructure(); } /// The GetJob function retrieves information about a specified print job. /// /// A handle to the printer for which the print-job data is retrieved. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// /// Identifies the print job for which to retrieve data. Use the AddJob function or StartDoc function to get a print /// job identifier. /// /// /// The type of information returned in the pJob buffer. If Level is 1, pJob receives a JOB_INFO_1 structure. If Level is 2, /// pJob receives a JOB_INFO_2 structure. /// /// /// /// A pointer to a buffer that receives a JOB_INFO_1 or a JOB_INFO_2 structure containing information about the job. /// The buffer must be large enough to store the strings pointed to by the structure members. /// /// /// To determine the required buffer size, call GetJob with cbBuf set to zero. GetJob fails, GetLastError /// returns ERROR_INSUFFICIENT_BUFFER, and the pcbNeeded parameter returns the size, in bytes, of the buffer required to hold the /// array of structures and their data. /// /// /// The size, in bytes, of the array. /// /// A pointer to a value that specifies the number of bytes copied if the function succeeds or the number of bytes required if cbBuf /// is too small. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/getjob BOOL GetJob( _In_ HANDLE hPrinter, _In_ DWORD JobId, _In_ DWORD // Level, _Out_ LPBYTE pJob, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "57e59f84-d2a0-4722-b0fc-6673f7bb5c57")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetJob(HPRINTER hPrinter, uint JobId, uint Level, IntPtr pJob, uint cbBuf, out uint pcbNeeded); /// The GetJob function retrieves information about a specified print job. /// The type of the structure to get. This must be either JOB_INFO_1 or a JOB_INFO_2. /// /// A handle to the printer for which the print-job data is retrieved. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// /// Identifies the print job for which to retrieve data. Use the AddJob function or StartDoc function to get a print /// job identifier. /// /// A JOB_INFO_1 or a JOB_INFO_2 structure containing information about the job as specified by . /// [PInvokeData("winspool.h", MSDNShortId = "57e59f84-d2a0-4722-b0fc-6673f7bb5c57")] public static T GetJob(HPRINTER hPrinter, uint JobId) where T : struct { if (!TryGetLevel("JOB_INFO_", out var lvl)) throw new ArgumentException($"{nameof(GetJob)} cannot process a structure of type {typeof(T).Name}."); if (!GetJob(hPrinter, JobId, lvl, default, 0, out var sz)) Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_INSUFFICIENT_BUFFER); using var mem = new SafeCoTaskMemHandle(sz); if (!GetJob(hPrinter, JobId, lvl, mem, mem.Size, out sz)) Win32Error.ThrowLastError(); return mem.ToStructure(); } /// The GetPrinter function retrieves information about a specified printer. /// /// A handle to the printer for which the function retrieves information. Use the OpenPrinter or AddPrinter function /// to retrieve a printer handle. /// /// /// The level or type of structure that the function stores into the buffer pointed to by pPrinter. /// This value can be 1, 2, 3, 4, 5, 6, 7, 8 or 9. /// /// /// /// A pointer to a buffer that receives a structure containing information about the specified printer. The buffer must be large /// enough to receive the structure and any strings or other data to which the structure members point. If the buffer is too small, /// the pcbNeeded parameter returns the required buffer size. /// /// The type of structure is determined by the value of Level. /// /// /// Level /// Structure /// /// /// 1 /// A PRINTER_INFO_1 structure containing general printer information. /// /// /// 2 /// A PRINTER_INFO_2 structure containing detailed information about the printer. /// /// /// 3 /// A PRINTER_INFO_3 structure containing the printer's security information. /// /// /// 4 /// /// A PRINTER_INFO_4 structure containing minimal printer information, including the name of the printer, the name of the server, /// and whether the printer is remote or local. /// /// /// /// 5 /// A PRINTER_INFO_5 structure containing printer information such as printer attributes and time-out settings. /// /// /// 6 /// A PRINTER_INFO_6 structure specifying the status value of a printer. /// /// /// 7 /// A PRINTER_INFO_7 structure that indicates whether the printer is published in the directory service. /// /// /// 8 /// A PRINTER_INFO_8 structure specifying the global default printer settings. /// /// /// 9 /// A PRINTER_INFO_9 structure specifying the per-user default printer settings. /// /// /// /// The size, in bytes, of the buffer pointed to by pPrinter. /// /// A pointer to a variable that the function sets to the size, in bytes, of the printer information. If cbBuf is smaller than this /// value, GetPrinter fails, and the value represents the required buffer size. If cbBuf is equal to or greater than this /// value, GetPrinter succeeds, and the value represents the number of bytes stored in the buffer. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// The pDevMode member in the PRINTER_INFO_2, PRINTER_INFO_8, and PRINTER_INFO_9 structures can be /// NULL. When this happens, the printer is unusable until the driver is reinstalled successfully. /// /// /// For the PRINTER_INFO_2 and PRINTER_INFO_3 structures that contain a pointer to a security descriptor, the function /// retrieves only those components of the security descriptor that the caller has permission to read. To retrieve particular /// security descriptor components, you must specify the necessary access rights when you call the OpenPrinter function to /// retrieve a handle to the printer. The following table shows the access rights required to read the various security descriptor components. /// /// /// /// Access Right /// Security Descriptor Component /// /// /// READ_CONTROL /// Owner Primary group Discretionary access-control list (DACL) /// /// /// ACCESS_SYSTEM_SECURITY /// System access-control list (SACL) /// /// /// /// If you specify level 7, the dwAction member of PRINTER_INFO_7 returns one of the following values to indicate /// whether the printer is published in the directory service. /// /// /// /// dwAction value /// Meaning /// /// /// DSPRINT_PUBLISH /// /// The printer is published. The pszObjectGUID member contains the GUID of the directory services print queue object associated /// with the printer. /// /// /// /// DSPRINT_UNPUBLISH /// The printer is not published. /// /// /// DSPRINT_PENDING /// /// Indicates that the system is attempting to complete a publish or unpublish operation. If a SetPrinter call fails to publish or /// unpublish a printer, the system makes further attempts to complete the operation in the background. /// /// /// /// /// Starting with Windows Vista, the printer data returned by GetPrinter is retrieved from a local cache when hPrinter refers /// to a printer hosted by a print server and there is at least one open connection to the print server. In all other /// configurations, the printer data is queried from the print server. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/getprinter BOOL GetPrinter( _In_ HANDLE hPrinter, _In_ DWORD Level, // _Out_ LPBYTE pPrinter, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "f162edbb-83ee-40c3-8710-9c867301d652")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetPrinter(HPRINTER hPrinter, uint Level, IntPtr pPrinter, uint cbBuf, out uint pcbNeeded); /// The GetPrinter function retrieves information about a specified printer. /// /// The type of the structure to get. This must be either PRINTER_INFO_1, PRINTER_INFO_2, PRINTER_INFO_3, /// PRINTER_INFO_4, PRINTER_INFO_5, PRINTER_INFO_6, PRINTER_INFO_7, PRINTER_INFO_8, or JOB_INFO_9. /// /// /// A handle to the printer for which the function retrieves information. Use the OpenPrinter or AddPrinter function /// to retrieve a printer handle. /// /// /// A PRINTER_INFO_1, PRINTER_INFO_2, PRINTER_INFO_3, PRINTER_INFO_4, PRINTER_INFO_5, /// PRINTER_INFO_6, PRINTER_INFO_7, PRINTER_INFO_8, or JOB_INFO_9 structure containing information about /// the printer as specified by . /// /// /// /// The pDevMode member in the PRINTER_INFO_2, PRINTER_INFO_8, and PRINTER_INFO_9 structures can be /// NULL. When this happens, the printer is unusable until the driver is reinstalled successfully. /// /// /// For the PRINTER_INFO_2 and PRINTER_INFO_3 structures that contain a pointer to a security descriptor, the function /// retrieves only those components of the security descriptor that the caller has permission to read. To retrieve particular /// security descriptor components, you must specify the necessary access rights when you call the OpenPrinter function to /// retrieve a handle to the printer. The following table shows the access rights required to read the various security descriptor components. /// /// /// /// Access Right /// Security Descriptor Component /// /// /// READ_CONTROL /// Owner Primary group Discretionary access-control list (DACL) /// /// /// ACCESS_SYSTEM_SECURITY /// System access-control list (SACL) /// /// /// /// If you specify level 7, the dwAction member of PRINTER_INFO_7 returns one of the following values to indicate /// whether the printer is published in the directory service. /// /// /// /// dwAction value /// Meaning /// /// /// DSPRINT_PUBLISH /// /// The printer is published. The pszObjectGUID member contains the GUID of the directory services print queue object associated /// with the printer. /// /// /// /// DSPRINT_UNPUBLISH /// The printer is not published. /// /// /// DSPRINT_PENDING /// /// Indicates that the system is attempting to complete a publish or unpublish operation. If a SetPrinter call fails to publish or /// unpublish a printer, the system makes further attempts to complete the operation in the background. /// /// /// /// /// Starting with Windows Vista, the printer data returned by GetPrinter is retrieved from a local cache when hPrinter refers /// to a printer hosted by a print server and there is at least one open connection to the print server. In all other /// configurations, the printer data is queried from the print server. /// /// public static T GetPrinter(HPRINTER hPrinter) where T : struct { if (!TryGetLevel("PRINTER_INFO_", out var lvl)) throw new ArgumentException($"{nameof(GetPrinter)} cannot process a structure of type {typeof(T).Name}."); if (!GetPrinter(hPrinter, lvl, default, 0, out var sz)) Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_INSUFFICIENT_BUFFER); using var mem = new SafeCoTaskMemHandle(sz); if (!GetPrinter(hPrinter, lvl, mem, mem.Size, out sz)) Win32Error.ThrowLastError(); return mem.ToStructure(); } /// /// The GetPrinterData function retrieves configuration data for the specified printer or print server. /// /// In Windows 2000 and later versions of Windows, calling GetPrinterData is equivalent to calling GetPrinterDataEx /// with the pKeyName parameter set to "PrinterDriverData". /// /// /// /// A handle to the printer or print server for which the function retrieves configuration data. Use the OpenPrinter, /// OpenPrinter2, or AddPrinter function to retrieve a printer handle. /// /// /// A pointer to a null-terminated string that identifies the data to retrieve. /// For printers, this string is the name of a registry value under the printer's "PrinterDriverData" key in the registry. /// For print servers, this string is one of the predefined strings listed in the following Remarks section. /// /// /// A pointer to a variable that receives a value that indicates the type of data retrieved in pData. The function returns the type /// specified in the SetPrinterData or SetPrinterDataEx call that stored the data. Set this parameter to NULL /// if you don't need the data type. /// /// A pointer to a buffer that receives the configuration data. /// The size, in bytes, of the buffer that pData points to. /// /// A pointer to a variable that receives the size, in bytes, of the configuration data. If the buffer size specified by nSize is /// too small, the function returns ERROR_MORE_DATA, and pcbNeeded indicates the required buffer size. /// /// /// If the function succeeds, the return value is ERROR_SUCCESS. If the function fails, the return value is an error value. /// /// /// /// GetPrinterData retrieves printer configuration data that was set by the SetPrinterDataEx or SetPrinterData function. /// /// /// GetPrinterData might trigger a Windows call to GetPrinterDataFromPort, which might write to the registry. If it /// does, side effects can occur, such as triggering an update or upgrade printer event ID 20 in the client, if the printer is /// shared in a network. /// /// If hPrinter is a handle to a print server, pValueName can specify one of the following predefined values. /// /// /// Value /// Comments /// /// /// SPLREG_ALLOW_USER_MANAGEFORMS /// Windows XP with Service Pack 2 (SP2) and later Windows Server 2003 with Service Pack 1 (SP1) and later /// /// /// SPLREG_ARCHITECTURE /// /// /// /// SPLREG_BEEP_ENABLED /// /// /// /// SPLREG_DEFAULT_SPOOL_DIRECTORY /// /// /// /// SPLREG_DNS_MACHINE_NAME /// /// /// /// SPLREG_DS_PRESENT /// On successful return, pData contains 0x0001 if the machine is on a DS domain, 0 otherwise. /// /// /// SPLREG_DS_PRESENT_FOR_USER /// On successful return, pData contains 0x0001 if the user is logged onto a DS domain, 0 otherwise. /// /// /// SPLREG_EVENT_LOG /// /// /// /// SPLREG_MAJOR_VERSION /// /// /// /// SPLREG_MINOR_VERSION /// /// /// /// SPLREG_NET_POPUP /// Not supported in Windows Server 2003 and later /// /// /// SPLREG_NET_POPUP_TO_COMPUTER /// /// On successful return, pData contains 1 if job notifications should be sent to the client computer, or 0 if job notifications are /// to be sent to the user. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_OS_VERSION /// Windows XP and later /// /// /// SPLREG_OS_VERSIONEX /// /// /// /// SPLREG_PORT_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_PORT_THREAD_PRIORITY /// /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_GROUPS /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_TIME_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_MAX_OBJECTS_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_IDLE_TIMEOUT /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_EXECUTION_POLICY /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_OVERRIDE_POLICY /// Windows 7 and later /// /// /// SPLREG_REMOTE_FAX /// On successful return, pData contains 0x0001 if the FAX service supports remote clients, 0 otherwise. /// /// /// SPLREG_RETRY_POPUP /// /// On successful return, pData contains 1 if server is set to retry pop-up windows for all jobs, or 0 if server does not retry /// pop-up windows for all jobs. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_WEBSHAREMGMT /// Windows Server 2003 and later /// /// /// The following values of pValueName indicate the pool printing behavior when an error occurs. /// /// /// Value /// Comments /// /// /// SPLREG_RESTART_JOB_ON_POOL_ERROR /// /// The value of pData indicates the time, in seconds, when a job is restarted on another port after an error occurs. This setting /// is used with SPLREG_RESTART_JOB_ON_POOL_ENABLED. /// /// /// /// SPLREG_RESTART_JOB_ON_POOL_ENABLED /// A nonzero value in pData indicates that SPLREG_RESTART_JOB_ON_POOL_ERROR is enabled. /// /// /// /// The time specified in SPLREG_RESTART_JOB_ON_POOL_ERROR is a minimum time. The actual time can be longer, depending on the /// following port monitor settings, which are registry values under this registry key: /// /// HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors\<MonitorName>\Ports /// Call the RegQueryValueEx function to query these values. /// /// /// Port monitor setting /// Data type /// Meaning /// /// /// StatusUpdateEnabled /// REG_DWORD /// If a nonzero value, enables the port monitor to update the spooler with the port status. /// /// /// StatusUpdateInterval /// REG_DWORD /// Specifies the interval, in minutes, when the port monitor updates the spooler with the port status. /// /// /// /// In Windows 7 and later versions of Windows, print jobs that are sent to a print server are rendered on the client by default. /// The following values configure client-side rendering of a print jobs and can be read if you set the following values in pValueName. /// /// /// /// Setting /// Data type /// Description /// /// /// EMFDespoolingSetting /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, enables the default client-side rendering of print jobs. A value /// of 1 disables client-side rendering of print jobs. /// /// /// /// ForceClientSideRendering /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, will cause the print jobs to be rendered on the client. If a /// print job cannot be rendered on the client, it will be rendered on the server. If a print job cannot be rendered on the server, /// it will fail. A value of 1 will render print jobs on the client. If a print job cannot be rendered on the client, it will fail. /// /// /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/getprinterdata DWORD GetPrinterData( _In_ HANDLE hPrinter, _In_ LPTSTR // pValueName, _Out_ LPDWORD pType, _Out_ LPBYTE pData, _In_ DWORD nSize, _Out_ LPDWORD pcbNeeded ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "b5a44b27-a4aa-4e58-9a64-05be87d12ab5")] public static extern Win32Error GetPrinterData(HPRINTER hPrinter, string pValueName, out REG_VALUE_TYPE pType, IntPtr pData, uint nSize, out uint pcbNeeded); /// /// The GetPrinterData function retrieves configuration data for the specified printer or print server. /// /// In Windows 2000 and later versions of Windows, calling GetPrinterData is equivalent to calling GetPrinterDataEx /// with the pKeyName parameter set to "PrinterDriverData". /// /// /// /// A handle to the printer or print server for which the function retrieves configuration data. Use the OpenPrinter, /// OpenPrinter2, or AddPrinter function to retrieve a printer handle. /// /// /// A pointer to a null-terminated string that identifies the data to retrieve. /// For printers, this string is the name of a registry value under the printer's "PrinterDriverData" key in the registry. /// For print servers, this string is one of the predefined strings listed in the following Remarks section. /// /// THe requested configuration data. /// /// /// GetPrinterData retrieves printer configuration data that was set by the SetPrinterDataEx or SetPrinterData function. /// /// /// GetPrinterData might trigger a Windows call to GetPrinterDataFromPort, which might write to the registry. If it /// does, side effects can occur, such as triggering an update or upgrade printer event ID 20 in the client, if the printer is /// shared in a network. /// /// If hPrinter is a handle to a print server, pValueName can specify one of the following predefined values. /// /// /// Value /// Comments /// /// /// SPLREG_ALLOW_USER_MANAGEFORMS /// Windows XP with Service Pack 2 (SP2) and later Windows Server 2003 with Service Pack 1 (SP1) and later /// /// /// SPLREG_ARCHITECTURE /// /// /// /// SPLREG_BEEP_ENABLED /// /// /// /// SPLREG_DEFAULT_SPOOL_DIRECTORY /// /// /// /// SPLREG_DNS_MACHINE_NAME /// /// /// /// SPLREG_DS_PRESENT /// On successful return, pData contains 0x0001 if the machine is on a DS domain, 0 otherwise. /// /// /// SPLREG_DS_PRESENT_FOR_USER /// On successful return, pData contains 0x0001 if the user is logged onto a DS domain, 0 otherwise. /// /// /// SPLREG_EVENT_LOG /// /// /// /// SPLREG_MAJOR_VERSION /// /// /// /// SPLREG_MINOR_VERSION /// /// /// /// SPLREG_NET_POPUP /// Not supported in Windows Server 2003 and later /// /// /// SPLREG_NET_POPUP_TO_COMPUTER /// /// On successful return, pData contains 1 if job notifications should be sent to the client computer, or 0 if job notifications are /// to be sent to the user. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_OS_VERSION /// Windows XP and later /// /// /// SPLREG_OS_VERSIONEX /// /// /// /// SPLREG_PORT_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_PORT_THREAD_PRIORITY /// /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_GROUPS /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_TIME_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_MAX_OBJECTS_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_IDLE_TIMEOUT /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_EXECUTION_POLICY /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_OVERRIDE_POLICY /// Windows 7 and later /// /// /// SPLREG_REMOTE_FAX /// On successful return, pData contains 0x0001 if the FAX service supports remote clients, 0 otherwise. /// /// /// SPLREG_RETRY_POPUP /// /// On successful return, pData contains 1 if server is set to retry pop-up windows for all jobs, or 0 if server does not retry /// pop-up windows for all jobs. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_WEBSHAREMGMT /// Windows Server 2003 and later /// /// /// The following values of pValueName indicate the pool printing behavior when an error occurs. /// /// /// Value /// Comments /// /// /// SPLREG_RESTART_JOB_ON_POOL_ERROR /// /// The value of pData indicates the time, in seconds, when a job is restarted on another port after an error occurs. This setting /// is used with SPLREG_RESTART_JOB_ON_POOL_ENABLED. /// /// /// /// SPLREG_RESTART_JOB_ON_POOL_ENABLED /// A nonzero value in pData indicates that SPLREG_RESTART_JOB_ON_POOL_ERROR is enabled. /// /// /// /// The time specified in SPLREG_RESTART_JOB_ON_POOL_ERROR is a minimum time. The actual time can be longer, depending on the /// following port monitor settings, which are registry values under this registry key: /// /// HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors\<MonitorName>\Ports /// Call the RegQueryValueEx function to query these values. /// /// /// Port monitor setting /// Data type /// Meaning /// /// /// StatusUpdateEnabled /// REG_DWORD /// If a nonzero value, enables the port monitor to update the spooler with the port status. /// /// /// StatusUpdateInterval /// REG_DWORD /// Specifies the interval, in minutes, when the port monitor updates the spooler with the port status. /// /// /// /// In Windows 7 and later versions of Windows, print jobs that are sent to a print server are rendered on the client by default. /// The following values configure client-side rendering of a print jobs and can be read if you set the following values in pValueName. /// /// /// /// Setting /// Data type /// Description /// /// /// EMFDespoolingSetting /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, enables the default client-side rendering of print jobs. A value /// of 1 disables client-side rendering of print jobs. /// /// /// /// ForceClientSideRendering /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, will cause the print jobs to be rendered on the client. If a /// print job cannot be rendered on the client, it will be rendered on the server. If a print job cannot be rendered on the server, /// it will fail. A value of 1 will render print jobs on the client. If a print job cannot be rendered on the client, it will fail. /// /// /// /// [PInvokeData("winspool.h", MSDNShortId = "b5a44b27-a4aa-4e58-9a64-05be87d12ab5")] public static object GetPrinterData(HPRINTER hPrinter, string pValueName) { GetPrinterData(hPrinter, pValueName, out _, default, 0, out var sz).ThrowUnless(Win32Error.ERROR_MORE_DATA); using var mem = new SafeCoTaskMemHandle(sz); GetPrinterData(hPrinter, pValueName, out var type, mem, mem.Size, out sz).ThrowIfFailed(); return type.GetValue(mem, mem.Size); } /// /// The GetPrinterDataEx function retrieves configuration data for the specified printer or print server. /// GetPrinterDataEx can retrieve values that the SetPrinterData function stored. In addition, GetPrinterDataEx /// can retrieve values that the SetPrinterDataEx function stored under a specified key. /// /// /// A handle to the printer or print server for which the function retrieves configuration data. Use the OpenPrinter, /// OpenPrinter2, or AddPrinter function to retrieve a printer handle. /// /// /// /// A pointer to a null-terminated string that specifies the key containing the value to be retrieved. Use the backslash ( \ ) /// character as a delimiter to specify a path that has one or more subkeys. /// /// If hPrinter is a handle to a printer and pKeyName is NULL or an empty string, GetPrinterDataEx returns ERROR_INVALID_PARAMETER. /// If hPrinter is a handle to a print server, pKeyName is ignored. /// /// /// A pointer to a null-terminated string that identifies the data to retrieve. /// For printers, this string specifies the name of a value under the pKeyName key. /// For print servers, this string is one of the predefined strings listed in the following Remarks section. /// /// /// A pointer to a variable that receives the type of data stored in the value. The function returns the type specified in the /// SetPrinterDataEx call when the data was stored. This parameter can be NULL if you don't need the information. /// GetPrinterDataEx passes pType on as the lpdwType parameter of a RegQueryValueEx function call. /// /// A pointer to a buffer that receives the configuration data. /// The size, in bytes, of the buffer pointed to by pData. /// /// A pointer to a variable that receives the size, in bytes, of the configuration data. If the buffer size specified by nSize is /// too small, the function returns ERROR_MORE_DATA, and pcbNeeded indicates the required buffer size. /// /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is an error value. /// /// /// /// GetPrinterDataEx retrieves printer-configuration data that was set by the SetPrinterDataEx and /// SetPrinterData functions. /// /// /// Calling GetPrinterDataEx with the pKeyName parameter set to "PrinterDriverData" is equivalent to calling the /// GetPrinterData function. /// /// If hPrinter is a handle to a print server, pValueName can specify one of the following predefined values. /// /// /// Value /// Comments /// /// /// SPLREG_ALLOW_USER_MANAGEFORMS /// Windows XP with Service Pack 2 (SP2) and later Windows Server 2003 with Service Pack 1 (SP1) and later /// /// /// SPLREG_ARCHITECTURE /// /// /// /// SPLREG_BEEP_ENABLED /// /// /// /// SPLREG_DEFAULT_SPOOL_DIRECTORY /// /// /// /// SPLREG_DNS_MACHINE_NAME /// /// /// /// SPLREG_DS_PRESENT /// On successful return, pData contains 0x0001 if the machine is on a DS domain, 0 otherwise. /// /// /// SPLREG_DS_PRESENT_FOR_USER /// On successful return, pData contains 0x0001 if the user is logged onto a DS domain, 0 otherwise. /// /// /// SPLREG_EVENT_LOG /// /// /// /// SPLREG_MAJOR_VERSION /// /// /// /// SPLREG_MINOR_VERSION /// /// /// /// SPLREG_NET_POPUP /// Not supported in Windows Server 2003 and later /// /// /// SPLREG_NET_POPUP_TO_COMPUTER /// /// On successful return, pData contains 1 if job notifications should be sent to the client computer, or 0 if job notifications are /// to be sent to the user. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_OS_VERSION /// Windows XP and later /// /// /// SPLREG_OS_VERSIONEX /// /// /// /// SPLREG_PORT_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_PORT_THREAD_PRIORITY /// /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_GROUPS /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_TIME_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_MAX_OBJECTS_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_IDLE_TIMEOUT /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_EXECUTION_POLICY /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_OVERRIDE_POLICY /// Windows 7 and later /// /// /// SPLREG_REMOTE_FAX /// On successful return, pData contains 0x0001 if the FAX service supports remote clients, 0 otherwise. /// /// /// SPLREG_RETRY_POPUP /// /// On successful return, pData contains 1 if server is set to retry pop-up windows for all jobs, or 0 if server does not retry /// pop-up windows for all jobs. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_WEBSHAREMGMT /// Windows Server 2003 and later /// /// /// The following values of pValueName indicate the pool printing behavior when an error occurs. /// /// /// Value /// Comments /// /// /// SPLREG_RESTART_JOB_ON_POOL_ERROR /// /// The value of pData indicates the time, in seconds, when a job is restarted on another port after an error occurs. This setting /// is used with SPLREG_RESTART_JOB_ON_POOL_ENABLED. /// /// /// /// SPLREG_RESTART_JOB_ON_POOL_ENABLED /// A nonzero value in pData indicates that SPLREG_RESTART_JOB_ON_POOL_ERROR is enabled. /// /// /// /// The time specified in SPLREG_RESTART_JOB_ON_POOL_ERROR is a minimum time. The actual time can be longer, depending on the /// following port monitor settings, which are registry values under this registry key: /// /// HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors\<MonitorName>\Ports /// Call the RegQueryValueEx function to query these values. /// /// /// Port monitor setting /// Data type /// Meaning /// /// /// StatusUpdateEnabled /// REG_DWORD /// If a nonzero value, enables the port monitor to update the spooler with the port status. /// /// /// StatusUpdateInterval /// REG_DWORD /// Specifies the interval, in minutes, when the port monitor updates the spooler with the port status. /// /// /// /// If pKeyName is one of the predefined Directory Service (DS) keys (see SetPrinter) and pValueName contains a comma (','), /// then the portion of pValueName before the comma is the value name and the portion of pValueName to the right of the comma is the /// DS Property OID. A subkey called OID is created and a new value that consists of the value name and OID is entered under the OID /// key. SetPrinterDataEx also adds the value name and data under the DS key. /// /// /// In Windows 7 and later versions of Windows, print jobs that are sent to a print server are rendered on the client by default. /// The configuration of client-side rendering for a printer can be read by setting pKeyName to "PrinterDriverData" and pValueName /// to the setting value in the following table. /// /// /// /// Setting /// Data type /// Description /// /// /// EMFDespoolingSetting /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, enables the default client-side rendering of print jobs. A value /// of 1 disables client-side rendering of print jobs. /// /// /// /// ForceClientSideRendering /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, will cause the print jobs to be rendered on the client. If a /// print job cannot be rendered on the client, it will be rendered on the server. If a print job cannot be rendered on the server, /// it will fail. A value of 1 will render print jobs on the client. If a print job cannot be rendered on the client, it will fail. /// /// /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/getprinterdataex DWORD GetPrinterDataEx( _In_ HANDLE hPrinter, _In_ // LPCTSTR pKeyName, _In_ LPCTSTR pValueName, _Out_ LPDWORD pType, _Out_ LPBYTE pData, _In_ DWORD nSize, _Out_ LPDWORD pcbNeeded ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "5d9183a7-97cc-46de-848e-e37ce51396eb")] public static extern Win32Error GetPrinterDataEx(HPRINTER hPrinter, string pKeyName, string pValueName, out REG_VALUE_TYPE pType, IntPtr pData, uint nSize, out uint pcbNeeded); /// /// The GetPrinterDataEx function retrieves configuration data for the specified printer or print server. /// GetPrinterDataEx can retrieve values that the SetPrinterData function stored. In addition, GetPrinterDataEx /// can retrieve values that the SetPrinterDataEx function stored under a specified key. /// /// /// A handle to the printer or print server for which the function retrieves configuration data. Use the OpenPrinter, /// OpenPrinter2, or AddPrinter function to retrieve a printer handle. /// /// /// /// A pointer to a null-terminated string that specifies the key containing the value to be retrieved. Use the backslash ( \ ) /// character as a delimiter to specify a path that has one or more subkeys. /// /// If hPrinter is a handle to a printer and pKeyName is NULL or an empty string, GetPrinterDataEx returns ERROR_INVALID_PARAMETER. /// If hPrinter is a handle to a print server, pKeyName is ignored. /// /// /// A pointer to a null-terminated string that identifies the data to retrieve. /// For printers, this string specifies the name of a value under the pKeyName key. /// For print servers, this string is one of the predefined strings listed in the following Remarks section. /// /// The requested valued. /// /// /// GetPrinterDataEx retrieves printer-configuration data that was set by the SetPrinterDataEx and /// SetPrinterData functions. /// /// /// Calling GetPrinterDataEx with the pKeyName parameter set to "PrinterDriverData" is equivalent to calling the /// GetPrinterData function. /// /// If hPrinter is a handle to a print server, pValueName can specify one of the following predefined values. /// /// /// Value /// Comments /// /// /// SPLREG_ALLOW_USER_MANAGEFORMS /// Windows XP with Service Pack 2 (SP2) and later Windows Server 2003 with Service Pack 1 (SP1) and later /// /// /// SPLREG_ARCHITECTURE /// /// /// /// SPLREG_BEEP_ENABLED /// /// /// /// SPLREG_DEFAULT_SPOOL_DIRECTORY /// /// /// /// SPLREG_DNS_MACHINE_NAME /// /// /// /// SPLREG_DS_PRESENT /// On successful return, pData contains 0x0001 if the machine is on a DS domain, 0 otherwise. /// /// /// SPLREG_DS_PRESENT_FOR_USER /// On successful return, pData contains 0x0001 if the user is logged onto a DS domain, 0 otherwise. /// /// /// SPLREG_EVENT_LOG /// /// /// /// SPLREG_MAJOR_VERSION /// /// /// /// SPLREG_MINOR_VERSION /// /// /// /// SPLREG_NET_POPUP /// Not supported in Windows Server 2003 and later /// /// /// SPLREG_NET_POPUP_TO_COMPUTER /// /// On successful return, pData contains 1 if job notifications should be sent to the client computer, or 0 if job notifications are /// to be sent to the user. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_OS_VERSION /// Windows XP and later /// /// /// SPLREG_OS_VERSIONEX /// /// /// /// SPLREG_PORT_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_PORT_THREAD_PRIORITY /// /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_GROUPS /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_TIME_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_MAX_OBJECTS_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_IDLE_TIMEOUT /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_EXECUTION_POLICY /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_OVERRIDE_POLICY /// Windows 7 and later /// /// /// SPLREG_REMOTE_FAX /// On successful return, pData contains 0x0001 if the FAX service supports remote clients, 0 otherwise. /// /// /// SPLREG_RETRY_POPUP /// /// On successful return, pData contains 1 if server is set to retry pop-up windows for all jobs, or 0 if server does not retry /// pop-up windows for all jobs. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_WEBSHAREMGMT /// Windows Server 2003 and later /// /// /// The following values of pValueName indicate the pool printing behavior when an error occurs. /// /// /// Value /// Comments /// /// /// SPLREG_RESTART_JOB_ON_POOL_ERROR /// /// The value of pData indicates the time, in seconds, when a job is restarted on another port after an error occurs. This setting /// is used with SPLREG_RESTART_JOB_ON_POOL_ENABLED. /// /// /// /// SPLREG_RESTART_JOB_ON_POOL_ENABLED /// A nonzero value in pData indicates that SPLREG_RESTART_JOB_ON_POOL_ERROR is enabled. /// /// /// /// The time specified in SPLREG_RESTART_JOB_ON_POOL_ERROR is a minimum time. The actual time can be longer, depending on the /// following port monitor settings, which are registry values under this registry key: /// /// HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors\<MonitorName>\Ports /// Call the RegQueryValueEx function to query these values. /// /// /// Port monitor setting /// Data type /// Meaning /// /// /// StatusUpdateEnabled /// REG_DWORD /// If a nonzero value, enables the port monitor to update the spooler with the port status. /// /// /// StatusUpdateInterval /// REG_DWORD /// Specifies the interval, in minutes, when the port monitor updates the spooler with the port status. /// /// /// /// If pKeyName is one of the predefined Directory Service (DS) keys (see SetPrinter) and pValueName contains a comma (','), /// then the portion of pValueName before the comma is the value name and the portion of pValueName to the right of the comma is the /// DS Property OID. A subkey called OID is created and a new value that consists of the value name and OID is entered under the OID /// key. SetPrinterDataEx also adds the value name and data under the DS key. /// /// /// In Windows 7 and later versions of Windows, print jobs that are sent to a print server are rendered on the client by default. /// The configuration of client-side rendering for a printer can be read by setting pKeyName to "PrinterDriverData" and pValueName /// to the setting value in the following table. /// /// /// /// Setting /// Data type /// Description /// /// /// EMFDespoolingSetting /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, enables the default client-side rendering of print jobs. A value /// of 1 disables client-side rendering of print jobs. /// /// /// /// ForceClientSideRendering /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, will cause the print jobs to be rendered on the client. If a /// print job cannot be rendered on the client, it will be rendered on the server. If a print job cannot be rendered on the server, /// it will fail. A value of 1 will render print jobs on the client. If a print job cannot be rendered on the client, it will fail. /// /// /// /// [PInvokeData("winspool.h", MSDNShortId = "5d9183a7-97cc-46de-848e-e37ce51396eb")] public static object GetPrinterDataEx(HPRINTER hPrinter, string pKeyName, string pValueName) { GetPrinterDataEx(hPrinter, pKeyName, pValueName, out _, default, 0, out var sz).ThrowUnless(Win32Error.ERROR_MORE_DATA); using var mem = new SafeCoTaskMemHandle(sz); GetPrinterDataEx(hPrinter, pKeyName, pValueName, out var type, mem, mem.Size, out sz).ThrowIfFailed(); return type.GetValue(mem, mem.Size); } /// The GetPrintExecutionData retrieves the current print context. /// A pointer to a variable that receives the address of the PRINT_EXECUTION_DATA structure. /// /// Returns TRUE if the function succeeds; otherwise FALSE. If the return value is FALSE, call /// GetLastError to get the error status. /// /// /// /// Printer drivers should call GetProcAddress on the winspool.drv module to get the address of the /// GetPrintExecutionData function because GetPrintExecutionData is not supported on Windows Vista or earlier versions /// of Windows. /// /// GetPrintExecutionData only fails if the value of pData is NULL. /// /// The value of the clientAppPID member of PRINT_EXECUTION_DATA is only meaningful if the value of context is /// PRINT_EXECUTION_CONTEXT_WOW64. If the value of context is not PRINT_EXECUTION_CONTEXT_WOW64, the value of /// clientAppPID is 0. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/getprintexecutiondata BOOL WINAPI GetPrintExecutionData( _Out_ // PRINT_EXECUTION_DATA *pData ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "bb9506aa-a0da-46bc-a86a-84a79587cd50")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetPrintExecutionData(out PRINT_EXECUTION_DATA pData); /// /// The GetSpoolFileHandle function retrieves a handle for the spool file associated with the job currently submitted by the application. /// /// /// A handle to the printer to which the job was submitted. This should be the same handle that was used to submit the job. (Use the /// OpenPrinter or AddPrinter function to retrieve a printer handle.) /// /// /// If the function succeeds, it returns a handle to the spool file. /// If the function fails, it returns INVALID_HANDLE_VALUE. /// /// /// /// With the handle to the spool file, your application can write to the spool file with calls to WriteFile followed by CommitSpoolData. /// /// /// Your application must not call ClosePrinter on hPrinter until after it has accessed the spool file for the last time. /// Then it should call CloseSpoolFileHandle followed by ClosePrinter. Attempts to access the spool file handle after /// the original hPrinter has been closed will fail even if the file handle itself has not been closed. CloseSpoolFileHandle /// will itself fail if ClosePrinter is called first. /// /// This function will fail if it is called before the print job has finished spooling. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/getspoolfilehandle HANDLE GetSpoolFileHandle( _In_ HANDLE hPrinter ); [PInvokeData("winspool.h", MSDNShortId = "df6f28b3-66a6-4fb7-bdde-40cd7d934c5f")] public static SafeHSPOOLFILE GetSpoolFileHandle(HPRINTER hPrinter) => new SafeHSPOOLFILE(hPrinter, InternalGetSpoolFileHandle(hPrinter), true); /// The IsValidDevmode function verifies that the contents of a DEVMODE structure are valid. /// A pointer to the DEVMODE to validate. /// The size in bytes of the input byte buffer. /// /// /// TRUE, if the DEVMODE is structurally valid. If minor errors are found the function will fix them and return TRUE. /// /// /// FALSE, if the DEVMODE has one or more significant structural problems. For example, its dmSize member is /// misaligned or specifies a buffer that is too small. Also, FALSE if pDevmode is NULL. /// /// /// /// No private printer driver fields of the DEVMODE are checked, only the public fields. /// /// Callers should use dmSize+ dmDriverExtra for DevmodeSize only if they can guarantee that the input buffer /// size is at least that big. Since the DEVMODE is generally untrusted data, the values that are in the input buffer at the /// dmSize and dmDriverExtra offsets are also untrusted. /// /// This function is executable in Least-Privileged User Account (LUA) context. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/isvaliddevmode BOOL IsValidDevmode( _In_ PDEVMODE pDevmode, size_t // DevmodeSize ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "8b4e32cc-5eeb-4a0d-a1b7-f6edb99ed8d8")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsValidDevmode(in DEVMODE pDevmode, SizeT DevmodeSize); /// /// The OpenPrinter function retrieves a handle to the specified printer or print server or other types of handles in the /// print subsystem. /// /// /// /// A pointer to a null-terminated string that specifies the name of the printer or print server, the printer object, the /// XcvMonitor, or the XcvPort. /// /// /// For a printer object use: PrinterName, Job xxxx. For an XcvMonitor, use: ServerName, XcvMonitor MonitorName. For an XcvPort, /// use: ServerName, XcvPort PortName. /// /// If NULL, it indicates the local printer server. /// /// /// A pointer to a variable that receives a handle (not thread safe) to the open printer or print server object. /// /// The phPrinter parameter can return an Xcv handle for use with the XcvData function. For more information about XcvData, see the DDK. /// /// /// A pointer to a PRINTER_DEFAULTS structure. This value can be NULL. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// Do not call this method in DllMain. /// /// The handle pointed to by phPrinter is not thread safe. If callers need to use it concurrently on multiple threads, they must /// provide custom synchronization access to the printer handle using the Synchronization Functions. To avoid writing custom code /// the application can open a printer handle on each thread, as needed. /// /// /// The pDefault parameter enables you to specify the data type and device mode values that are used for printing documents /// submitted by the StartDocPrinter function. However, you can override these values by using the SetJob function /// after a document has been started. /// /// /// The DEVMODE settings defined in the PRINTER_DEFAULTS structure of the pDefault parameter are not used when the /// value of the pDatatype member of the DOC_INFO_1 structure that was passed in the pDocInfo parameter of the /// StartDocPrinter call is "RAW". When a high-level document (such as an Adobe PDF or Microsoft Word file) or other printer /// data (such PCL, PS, or HPGL) is sent directly to a printer with pDatatype set to "RAW", the document must fully describe the /// DEVMODE-style print job settings in the language understood by the hardware. /// /// /// You can call the OpenPrinter function to open a handle to a print server or to determine the access rights that a client /// has to a print server. To do so, specify the name of the print server in the pPrinterName parameter, set the pDatatype /// and pDevMode members of the PRINTER_DEFAULTS structure to NULL, and set the DesiredAccess member to /// specify a server access mask value such as SERVER_ALL_ACCESS. When you finish with the handle, pass it to the /// ClosePrinter function to close it. /// /// /// Use the DesiredAccess member of the PRINTER_DEFAULTS structure to specify the access rights that you need to the /// printer. The access rights can be one of the following. (If pDefault is NULL, then the access rights are PRINTER_ACCESS_USE.) /// /// /// /// Desired Access value /// Meaning /// /// /// PRINTER_ACCESS_ADMINISTER /// To perform administrative tasks, such as those provided by SetPrinter. /// /// /// PRINTER_ACCESS_USE /// To perform basic printing operations. /// /// /// PRINTER_ALL_ACCESS /// To perform all administrative tasks and basic printing operations except for SYNCHRONIZE (see Standard Access Rights. /// /// /// PRINTER_ACCESS_MANAGE_LIMITED /// /// To perform administrative tasks, such as those provided by SetPrinter and SetPrinterData. This value is available starting from /// Windows 8.1. /// /// /// /// generic security values, such as WRITE_DAC /// To allow specific control access rights. See Standard Access Rights. /// /// /// /// If a user does not have permission to open a specified printer or print server with the desired access, the OpenPrinter /// call will fail with a return value of zero and GetLastError will return the value ERROR_ACCESS_DENIED. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/openprinter BOOL OpenPrinter( _In_ LPTSTR pPrinterName, _Out_ LPHANDLE // phPrinter, _In_ LPPRINTER_DEFAULTS pDefault ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "96763220-d851-46f0-8be8-403f3356edb9")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool OpenPrinter(string pPrinterName, out SafeHPRINTER phPrinter, [In, Optional, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PRINTER_DEFAULTS_Marshaler))] PRINTER_DEFAULTS pDefault); /// /// Retrieves a handle to the specified printer, print server, or other types of handles in the print subsystem, while setting some /// of the printer options. /// /// /// /// A pointer to a constant null-terminated string that specifies the name of the printer or print server, the printer object, the /// XcvMonitor, or the XcvPort. /// /// /// For a printer object, use: PrinterName,Job xxxx. For an XcvMonitor, use: ServerName,XcvMonitor MonitorName. For an XcvPort, use: /// ServerName,XcvPort PortName. /// /// Windows Vista: If NULL, it indicates the local print server. /// /// A pointer to a variable that receives a handle to the open printer or print server object. /// A pointer to a PRINTER_DEFAULTS structure. This value can be NULL. /// A pointer to a PRINTER_OPTIONS structure. This value can be NULL. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. For extended error information, call GetLastError. /// /// /// Do not call this method in DllMain. /// The ANSI version of this function is not implemented and returns ERROR_NOT_SUPPORTED. /// /// The pDefault parameter enables you to specify the data type and device mode values that are used for printing documents /// submitted by the StartDocPrinter function. However, you can override these values by using the SetJob function /// after a document has been started. /// /// /// You can call the OpenPrinter2 function to open a handle to a print server or to determine client access rights to a print /// server. To do this, specify the name of the print server in the pPrinterName parameter, set the pDatatype and /// pDevMode members of the PRINTER_DEFAULTS structure to NULL, and set the DesiredAccess member to /// specify a server access mask value such as SERVER_ALL_ACCESS. When you are finished with the handle, pass it to the /// ClosePrinter function to close it. /// /// /// Use the DesiredAccess member of the PRINTER_DEFAULTS structure to specify the necessary access rights. The access /// rights can be one of the following. /// /// /// /// Desired Access value /// Meaning /// /// /// PRINTER_ACCESS_ADMINISTER /// To perform administrative tasks, such as those provided by SetPrinter. /// /// /// PRINTER_ACCESS_USE /// To perform basic printing operations. /// /// /// PRINTER_ALL_ACCESS /// To perform all administrative tasks and basic printing operations except SYNCHRONIZE. See Standard Access Rights. /// /// /// PRINTER_ACCESS_MANAGE_LIMITED /// /// To perform administrative tasks, such as those provided by SetPrinter and SetPrinterData. This value is available starting from /// Windows 8.1. /// /// /// /// generic security values, such as WRITE_DAC /// To allow specific control access rights. See Standard Access Rights. /// /// /// /// If a user does not have permission to open a specified printer or print server with the desired access, the OpenPrinter2 /// call will fail, and GetLastError will return the value ERROR_ACCESS_DENIED. /// /// /// When pPrinterName is a local printer, then OpenPrinter2 ignores all values of the dwFlags that the /// PRINTER_OPTIONS structure pointed to using pOptions, except PRINTER_OPTION_CLIENT_CHANGE. If the latter is passed, then /// OpenPrinter2 will return ERROR_ACCESS_DENIED. Accordingly, when opening a local printer, OpenPrinter2 provides no /// advantage over OpenPrinter. /// /// /// Windows Vista: The printer data returned by OpenPrinter2 is retrieved from a local cache unless the /// PRINTER_OPTION_NO_CACHE flag is set in the dwFlags field of the PRINTER_OPTIONS structure referenced by pOptions. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/openprinter2 BOOL OpenPrinter2( _In_ LPCTSTR pPrinterName, _Out_ // LPHANDLE phPrinter, _In_ LPPRINTER_DEFAULTS pDefault, _In_ PPRINTER_OPTIONS pOptions ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "e2370ae4-4475-4ccc-a6f9-3d33d1370054")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool OpenPrinter2(string pPrinterName, out SafeHPRINTER phPrinter, [In, Optional, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PRINTER_DEFAULTS_Marshaler))] PRINTER_DEFAULTS pDefault, in PRINTER_OPTIONS pOptions); /// The PrinterProperties function displays a printer-properties property sheet for the specified printer. /// A handle to the parent window of the property sheet. /// /// A handle to a printer object. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/printerproperties BOOL PrinterProperties( _In_ HWND hWnd, _In_ HANDLE // hPrinter ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "1d4c961b-178b-47af-b983-5b7327919f93")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool PrinterProperties(HWND hWnd, HPRINTER hPrinter); /// The ReadPrinter function retrieves data from the specified printer. /// /// A handle to the printer object for which to retrieve data. Use the OpenPrinter function to retrieve a printer object /// handle. Use the format: Printername, Job xxxx. /// /// A pointer to a buffer that receives the printer data. /// The size, in bytes, of the buffer to which pBuf points. /// /// A pointer to a variable that receives the number of bytes of data copied into the array to which pBuf points. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// ReadPrinter returns an error if the device or the printer is not bidirectional. // https://docs.microsoft.com/en-us/windows/win32/printdocs/readprinter BOOL ReadPrinter( _In_ HANDLE hPrinter, _Out_ LPVOID pBuf, // _In_ DWORD cbBuf, _Out_ LPDWORD pNoBytesRead ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "d7c3f186-c53e-424b-89bf-6742babb998f")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ReadPrinter(HPRINTER hPrinter, IntPtr pBuf, uint cbBuf, out uint pNoBytesRead); /// /// Reports to the Print Spooler service whether an XPS print job is in the spooling or the rendering phase and what part of the /// processing is currently underway. /// /// /// A printer handle for which the function is to retrieve information. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// /// Identifies the print job for which to retrieve data. Use the AddJob function or StartDoc function to get a print /// job identifier. /// /// Specifies whether the job is in the spooling phase or the rendering phase. /// /// Specifies what part of the processing is currently underway. This value refers to events in either the spooling or rendering /// phase depending on the value of jobOperation. /// /// /// If the operation succeeds, the return value is S_OK, otherwise the HRESULT will contain an error code. /// For more information about COM error codes, see Error Handling. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/reportjobprocessingprogress HRESULT ReportJobProcessingProgress( _In_ // HANDLE printerHandle, _In_ ULONG jobId, EPrintXPSJobOperation jobOperation, EPrintXPSJobProgress jobProgress ); [DllImport(Lib.Winspool, SetLastError = false, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "66f7483d-be98-410d-b0c7-430743397de2")] public static extern HRESULT ReportJobProcessingProgress(HPRINTER printerHandle, uint jobId, EPrintXPSJobOperation jobOperation, EPrintXPSJobProgress jobProgress); /// /// The ResetPrinter function specifies the data type and device mode values to be used for printing documents submitted by /// the StartDocPrinter function. These values can be overridden by using the SetJob function after document printing /// has started. /// /// /// Handle to the printer. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// /// Pointer to a PRINTER_DEFAULTS structure. /// /// The ResetPrinter function ignores the DesiredAccess member of the PRINTER_DEFAULTS structure. Set that /// member to zero. /// /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/resetprinter BOOL ResetPrinter( _In_ HANDLE hPrinter, _In_ // LPPRINTER_DEFAULTS pDefault ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "9efc6629-dbb7-4320-90b9-07c66f0add47")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ResetPrinter(HPRINTER hPrinter, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PRINTER_DEFAULTS_Marshaler))] PRINTER_DEFAULTS pDefault); /// The ScheduleJob function requests that the print spooler schedule a specified print job for printing. /// /// /// A handle to the printer for the print job. This must be a local printer that is configured as a spooled printer. If hPrinter is /// a handle to a remote printer connection, or if the printer is configured for direct printing, the ScheduleJob function /// fails. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// hPrinter must be the same printer handle specified in the call to AddJob that obtained the dwJobID print job identifier. /// /// The print job to be scheduled. You obtain this print job identifier by calling the AddJob function. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// You must successfully call the AddJob function before calling the ScheduleJob function. AddJob obtains the /// print job identifier that you pass to ScheduleJob as dwJobID. Both calls must use the same value for hPrinter. /// /// /// The ScheduleJob function checks for a valid spool file. If there is an invalid spool file, or if it is empty, /// ScheduleJob deletes both the spool file and the corresponding print job entry in the print spooler. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/schedulejob BOOL ScheduleJob( _In_ HANDLE hPrinter, _In_ DWORD dwJobID ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "a103a29c-be4d-491e-9b04-84571fe969a5")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ScheduleJob(HPRINTER hPrinter, uint dwJobID); /// /// The SetDefaultPrinter function sets the printer name of the default printer for the current user on the local computer. /// /// /// /// A pointer to a null-terminated string containing the default printer name. For a remote printer connection, the name format is /// **\\ server\**printername. For a local printer, the name format is printername. /// /// /// If this parameter is NULL or an empty string, that is, "", SetDefaultPrinter will select a default printer from /// one of the installed printers. If a default printer already exists, calling SetDefaultPrinter with a NULL or an /// empty string in this parameter might change the default printer. /// /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// When using this method, you must specify a valid printer, driver, and port. If they are invalid, the APIs do not fail but the /// result is not defined. This could cause other programs to set the printer back to the previous valid printer. You can use /// EnumPrinters to retrieve the printer name, driver name, and port name of all available printers. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/setdefaultprinter BOOL SetDefaultPrinter( _In_ LPCTSTR pszPrinter ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "55eec548-577f-422b-80e3-8b23aa4d2159")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetDefaultPrinter(string pszPrinter); /// The SetForm function sets the form information for the specified printer. /// /// A handle to the printer for which the form information is set. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// /// A pointer to a null-terminated string that specifies the form name for which the form information is set. /// /// The version of the structure to which pForm points. This value must be 1 or 2. /// A pointer to a FORM_INFO_1 or FORM_INFO_2 structure. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// SetForm can be called multiple times for an existing FORM_INFO_2, each call adding additional pairs of /// pDisplayName and wLangId values. All languages versions of the form will get the Size and /// ImageableArea values of the FORM_INFO_2 in the most recent call to SetForm. /// /// If the caller is remote and the Level is 2, the StringType value of the FORM_INFO_2 cannot be STRING_MUIDLL. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/setform BOOL SetForm( _In_ HANDLE hPrinter, _In_ LPTSTR pFormName, _In_ // DWORD Level, _In_ LPTSTR pForm ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "05d5d495-952c-4a1d-8694-1004d0c2bcf6")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForm(HPRINTER hPrinter, string pFormName, uint Level, IntPtr pForm); /// The SetForm function sets the form information for the specified printer. /// The type of the value being set. /// /// A handle to the printer for which the form information is set. Use the OpenPrinter or AddPrinter function to /// retrieve a printer handle. /// /// A pointer to a string that specifies the form name for which the form information is set. /// A FORM_INFO_1 or FORM_INFO_2 structure. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// /// SetForm can be called multiple times for an existing FORM_INFO_2, each call adding additional pairs of /// pDisplayName and wLangId values. All languages versions of the form will get the Size and /// ImageableArea values of the FORM_INFO_2 in the most recent call to SetForm. /// /// If the caller is remote and the Level is 2, the StringType value of the FORM_INFO_2 cannot be STRING_MUIDLL. /// [PInvokeData("winspool.h", MSDNShortId = "05d5d495-952c-4a1d-8694-1004d0c2bcf6")] public static bool SetForm(HPRINTER hPrinter, string pFormName, in T pForm) where T : struct { if (!TryGetLevel("FORM_INFO_", out var lvl)) throw new ArgumentException($"{nameof(SetForm)} cannot process a structure of type {typeof(T).Name}."); using var mem = SafeCoTaskMemHandle.CreateFromStructure(pForm); return SetForm(hPrinter, pFormName, lvl, mem); } /// /// /// The SetJob function pauses, resumes, cancels, or restarts a print job on a specified printer. You can also use the /// SetJob function to set print job parameters, such as the print job priority and the document name. /// /// /// You can use the SetJob function to give a command to a print job, or to set print job parameters, or to do both in the /// same call. The value of the Command parameter does not affect how the function uses the Level and pJob parameters. Also, you can /// use SetJob with JOB_INFO_3 to link together a set of print jobs. See Remarks for more information. /// /// /// /// A handle to the printer object of interest. Use the OpenPrinter, OpenPrinter2, or AddPrinter function to /// retrieve a printer handle. /// /// /// /// Identifier that specifies the print job. You obtain a print job identifier by calling the AddJob function or the /// StartDoc function. /// /// /// If the Level parameter is set to 3, the JobId parameter must match the JobId member of the JOB_INFO_3 structure /// pointed to by pJob /// /// /// /// The type of job information structure pointed to by the pJob parameter. /// /// All versions of Windows: You can set the Level parameter to 0, 1, or 2. When you set Level to 0, pJob should be /// NULL. Use these values when you are not setting any print job parameters. /// /// You can also set the Level parameter to 3. /// Starting with Windows Vista: You can also set the Level parameter to 4. /// /// /// A pointer to a structure that sets the print job parameters. /// All versions of Windows: pJob can point to a JOB_INFO_1 or JOB_INFO_2 structure. /// /// pJob can also point to a JOB_INFO_3 structure. You must have JOB_ACCESS_ADMINISTER access permission for the jobs /// specified by the JobId and NextJobId members of the JOB_INFO_3 structure. /// /// Starting with Windows Vista: pJob can also point to a JOB_INFO_4 structure. /// If the Level parameter is 0, pJob should be NULL. /// /// /// The print job operation to perform. This parameter can be one of the following values. /// /// /// Value /// Meaning /// /// /// JOB_CONTROL_CANCEL /// Do not use. To delete a print job, use JOB_CONTROL_DELETE. /// /// /// JOB_CONTROL_PAUSE /// Pause the print job. /// /// /// JOB_CONTROL_RESTART /// Restart the print job. A job can only be restarted if it was printing. /// /// /// JOB_CONTROL_RESUME /// Resume a paused print job. /// /// /// JOB_CONTROL_DELETE /// Delete the print job. /// /// /// JOB_CONTROL_SENT_TO_PRINTER /// Used by port monitors to end the print job. /// /// /// JOB_CONTROL_LAST_PAGE_EJECTED /// Used by language monitors to end the print job. /// /// /// JOB_CONTROL_RETAIN /// Windows Vista and later: Keep the job in the queue after it prints. /// /// /// JOB_CONTROL_RELEASE /// Windows Vista and later: Release the print job. /// /// /// /// You can use the same call to the SetJob function to set print job parameters and to give a command to a print job. Thus, /// Command does not need to be 0 if you are setting print job parameters, although it can be. /// /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// You can use the SetJob function to set various print job parameters by supplying a pointer to a JOB_INFO_1, /// JOB_INFO_2, JOB_INFO_3, or JOB_INFO_4 structure that contains the necessary data. /// /// /// To remove or delete all of the print jobs for a particular printer, call the SetPrinter function with its Command /// parameter set to PRINTER_CONTROL_PURGE. /// /// /// The following members of a JOB_INFO_1, JOB_INFO_2, or JOB_INFO_4 structure are ignored on a call to /// SetJob: JobId, pPrinterName, pMachineName, pUserName, pDrivername, Size, /// Submitted, Time, and TotalPages. /// /// /// You must have PRINTER_ACCESS_ADMINISTER access permission for a printer in order to change a print job's position in the /// print queue. /// /// /// If you do not want to set a print job's position in the print queue, you should set the Position member of the /// JOB_INFO_1, JOB_INFO_2, or JOB_INFO_4 structure to JOB_POSITION_UNSPECIFIED. /// /// /// Use the SetJob function with the JOB_INFO_3 structure to link together a set of print jobs (also known as a /// chain). This is useful in situations where a single document consists of several parts that you want to render separately. To /// print jobs A, B, C, and D in order, call SetJob with JOB_INFO_4 to link A to B, B to C, and C to D. /// /// If you link print jobs, note the following: /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/setjob BOOL SetJob( _In_ HANDLE hPrinter, _In_ DWORD JobId, _In_ DWORD // Level, _In_ LPBYTE pJob, _In_ DWORD Command ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "21947c69-c517-4962-8eb7-b45ed4211d9a")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetJob(HPRINTER hPrinter, uint JobId, uint Level, IntPtr pJob, JOB_CONTROL Command = 0); /// /// /// The SetJob function pauses, resumes, cancels, or restarts a print job on a specified printer. You can also use the /// SetJob function to set print job parameters, such as the print job priority and the document name. /// /// /// You can use the SetJob function to give a command to a print job. /// /// /// A handle to the printer object of interest. Use the OpenPrinter, OpenPrinter2, or AddPrinter function to /// retrieve a printer handle. /// Identifier that specifies the print job. You obtain a print job identifier by calling the AddJob function or the /// StartDoc function. /// The print job operation to perform. This parameter can be one of the following values. /// /// /// Value /// Meaning /// /// /// JOB_CONTROL_CANCEL /// Do not use. To delete a print job, use JOB_CONTROL_DELETE. /// /// /// JOB_CONTROL_PAUSE /// Pause the print job. /// /// /// JOB_CONTROL_RESTART /// Restart the print job. A job can only be restarted if it was printing. /// /// /// JOB_CONTROL_RESUME /// Resume a paused print job. /// /// /// JOB_CONTROL_DELETE /// Delete the print job. /// /// /// JOB_CONTROL_SENT_TO_PRINTER /// Used by port monitors to end the print job. /// /// /// JOB_CONTROL_LAST_PAGE_EJECTED /// Used by language monitors to end the print job. /// /// /// JOB_CONTROL_RETAIN /// Windows Vista and later: Keep the job in the queue after it prints. /// /// /// JOB_CONTROL_RELEASE /// Windows Vista and later: Release the print job. /// /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// To remove or delete all of the print jobs for a particular printer, call the SetPrinter function with its Command /// parameter set to PRINTER_CONTROL_PURGE. /// [PInvokeData("winspool.h", MSDNShortId = "21947c69-c517-4962-8eb7-b45ed4211d9a")] public static bool SetJob(HPRINTER hPrinter, uint JobId, JOB_CONTROL Command) => SetJob(hPrinter, JobId, 0, default, Command); /// /// /// The SetJob function pauses, resumes, cancels, or restarts a print job on a specified printer. You can also use the /// SetJob function to set print job parameters, such as the print job priority and the document name. /// /// /// You can use the SetJob function to give a command to a print job, or to set print job parameters, or to do both in the /// same call. The value of the Command parameter does not affect how the function uses the Level and pJob parameters. Also, you can /// use SetJob with JOB_INFO_3 to link together a set of print jobs. See Remarks for more information. /// /// /// The type of the value being set. /// /// A handle to the printer object of interest. Use the OpenPrinter, OpenPrinter2, or AddPrinter function to /// retrieve a printer handle. /// /// /// /// Identifier that specifies the print job. You obtain a print job identifier by calling the AddJob function or the /// StartDoc function. /// /// /// If the Level parameter is set to 3, the JobId parameter must match the JobId member of the JOB_INFO_3 structure /// pointed to by pJob /// /// /// /// A pointer to a structure that sets the print job parameters. /// All versions of Windows: pJob can point to a JOB_INFO_1 or JOB_INFO_2 structure. /// /// pJob can also point to a JOB_INFO_3 structure. You must have JOB_ACCESS_ADMINISTER access permission for the jobs /// specified by the JobId and NextJobId members of the JOB_INFO_3 structure. /// /// Starting with Windows Vista: pJob can also point to a JOB_INFO_4 structure. /// If the Level parameter is 0, pJob should be NULL. /// /// /// The print job operation to perform. This parameter can be one of the following values. /// /// /// Value /// Meaning /// /// /// JOB_CONTROL_CANCEL /// Do not use. To delete a print job, use JOB_CONTROL_DELETE. /// /// /// JOB_CONTROL_PAUSE /// Pause the print job. /// /// /// JOB_CONTROL_RESTART /// Restart the print job. A job can only be restarted if it was printing. /// /// /// JOB_CONTROL_RESUME /// Resume a paused print job. /// /// /// JOB_CONTROL_DELETE /// Delete the print job. /// /// /// JOB_CONTROL_SENT_TO_PRINTER /// Used by port monitors to end the print job. /// /// /// JOB_CONTROL_LAST_PAGE_EJECTED /// Used by language monitors to end the print job. /// /// /// JOB_CONTROL_RETAIN /// Windows Vista and later: Keep the job in the queue after it prints. /// /// /// JOB_CONTROL_RELEASE /// Windows Vista and later: Release the print job. /// /// /// /// You can use the same call to the SetJob function to set print job parameters and to give a command to a print job. Thus, /// Command does not need to be 0 if you are setting print job parameters, although it can be. /// /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// /// You can use the SetJob function to set various print job parameters by supplying a pointer to a JOB_INFO_1, /// JOB_INFO_2, JOB_INFO_3, or JOB_INFO_4 structure that contains the necessary data. /// /// /// To remove or delete all of the print jobs for a particular printer, call the SetPrinter function with its Command /// parameter set to PRINTER_CONTROL_PURGE. /// /// /// The following members of a JOB_INFO_1, JOB_INFO_2, or JOB_INFO_4 structure are ignored on a call to /// SetJob: JobId, pPrinterName, pMachineName, pUserName, pDrivername, Size, /// Submitted, Time, and TotalPages. /// /// /// You must have PRINTER_ACCESS_ADMINISTER access permission for a printer in order to change a print job's position in the /// print queue. /// /// /// If you do not want to set a print job's position in the print queue, you should set the Position member of the /// JOB_INFO_1, JOB_INFO_2, or JOB_INFO_4 structure to JOB_POSITION_UNSPECIFIED. /// /// /// Use the SetJob function with the JOB_INFO_3 structure to link together a set of print jobs (also known as a /// chain). This is useful in situations where a single document consists of several parts that you want to render separately. To /// print jobs A, B, C, and D in order, call SetJob with JOB_INFO_4 to link A to B, B to C, and C to D. /// /// If you link print jobs, note the following: /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// [PInvokeData("winspool.h", MSDNShortId = "21947c69-c517-4962-8eb7-b45ed4211d9a")] public static bool SetJob(HPRINTER hPrinter, uint JobId, in T pJob, JOB_CONTROL Command = 0) where T : struct { if (!TryGetLevel("JOB_INFO_", out var lvl)) throw new ArgumentException($"{nameof(SetJob)} cannot process a structure of type {typeof(T).Name}."); using var mem = SafeCoTaskMemHandle.CreateFromStructure(pJob); return SetJob(hPrinter, JobId, lvl, mem, Command); } /// The SetPort function sets the status associated with a printer port. /// /// Pointer to a zero-terminated string that specifies the name of the printer server to which the port is connected. Set this /// parameter to NULL if the port is on the local machine. /// /// Pointer to a zero-terminated string that specifies the name of the printer port. /// /// Specifies the type of structure pointed to by the pPortInfo parameter. /// This value must be 3, which corresponds to a PORT_INFO_3 data structure. /// /// Pointer to a PORT_INFO_3 structure that contains the port status information to set. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// The caller of the SetPort function must be executing as an Administrator. Additionally, if the caller is a Port Monitor /// or Language Monitor, it must call RevertToSelf to cease impersonation before it calls SetPort. /// /// All programs that call SetPort must have SERVER_ACCESS_ADMINISTER access to the server to which the port is connected. /// /// When you set a printer port status value with the severity value PORT_STATUS_TYPE_ERROR, the print spooler stops sending jobs to /// the port. The print spooler resumes sending jobs to the port when the port status is cleared by another call to SetPort. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/setport BOOL SetPort( _In_ LPTSTR pName, _In_ LPTSTR pPortName, _In_ // DWORD dwLevel, _In_ LPBYTE pPortInfo ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "1b80ad93-aaa1-41ed-a668-a944fa62c3eb")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetPort([Optional] string pName, string pPortName, uint dwLevel, IntPtr pPortInfo); /// The SetPort function sets the status associated with a printer port. /// /// A string that specifies the name of the printer server to which the port is connected. Set this parameter to /// if the port is on the local machine. /// /// A string that specifies the name of the printer port. /// The new port status value. /// The severity of the port status value. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// The caller of the SetPort function must be executing as an Administrator. Additionally, if the caller is a Port Monitor /// or Language Monitor, it must call RevertToSelf to cease impersonation before it calls SetPort. /// /// All programs that call SetPort must have SERVER_ACCESS_ADMINISTER access to the server to which the port is connected. /// /// When you set a printer port status value with the severity value PORT_STATUS_TYPE_ERROR, the print spooler stops sending jobs to /// the port. The print spooler resumes sending jobs to the port when the port status is cleared by another call to SetPort. /// /// [PInvokeData("winspool.h", MSDNShortId = "1b80ad93-aaa1-41ed-a668-a944fa62c3eb")] public static bool SetPort([Optional] string pName, string pPortName, PORT_STATUS status, PORT_STATUS_TYPE severity) { using var mem = SafeCoTaskMemHandle.CreateFromStructure(new PORT_INFO_3 { dwStatus = status, dwSeverity = severity }); return SetPort(pName, pPortName, 3, mem); } /// The SetPort function sets the status associated with a printer port. /// /// A string that specifies the name of the printer server to which the port is connected. Set this parameter to /// if the port is on the local machine. /// /// A string that specifies the name of the printer port. /// /// A new printer port status value string to set. Use this member if there is no suitable status value among those listed for . /// /// The severity of the port status value. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// /// The caller of the SetPort function must be executing as an Administrator. Additionally, if the caller is a Port Monitor /// or Language Monitor, it must call RevertToSelf to cease impersonation before it calls SetPort. /// /// All programs that call SetPort must have SERVER_ACCESS_ADMINISTER access to the server to which the port is connected. /// /// When you set a printer port status value with the severity value PORT_STATUS_TYPE_ERROR, the print spooler stops sending jobs to /// the port. The print spooler resumes sending jobs to the port when the port status is cleared by another call to SetPort. /// /// [PInvokeData("winspool.h", MSDNShortId = "1b80ad93-aaa1-41ed-a668-a944fa62c3eb")] public static bool SetPort([Optional] string pName, string pPortName, string status, PORT_STATUS_TYPE severity) { using var mem = SafeCoTaskMemHandle.CreateFromStructure(new PORT_INFO_3 { pszStatus = status, dwSeverity = severity }); return SetPort(pName, pPortName, 3, mem); } /// /// The SetPrinter function sets the data for a specified printer or sets the state of the specified printer by pausing /// printing, resuming printing, or clearing all print jobs. /// /// /// A handle to the printer. Use the OpenPrinter, OpenPrinter2, or AddPrinter function to retrieve a printer handle. /// /// /// /// The type of data that the function stores into the buffer pointed to by pPrinter. If the Command parameter is not equal to zero, /// the Level parameter must be zero. /// /// This value can be 0, 2, 3, 4, 5, 6, 7, 8, or 9. /// /// /// /// A pointer to a buffer containing data to set for the printer, or containing information for the command specified by the Command /// parameter. The type of data in the buffer is determined by the value of Level. /// /// /// /// Level /// Structure /// /// /// 0 /// /// If the Command parameter is PRINTER_CONTROL_SET_STATUS, pPrinter must contain a DWORD value that specifies the new printer /// status to set. For a list of the possible status values, see the Status member of the PRINTER_INFO_2 structure. Note that /// PRINTER_STATUS_PAUSED and PRINTER_STATUS_PENDING_DELETION are not valid status values to set. If Level is 0, but the Command /// parameter is not PRINTER_CONTROL_SET_STATUS, pPrinter must be NULL. /// /// /// /// 2 /// A PRINTER_INFO_2 structure containing detailed information about the printer. /// /// /// 3 /// A PRINTER_INFO_3 structure containing the printer's security information. /// /// /// 4 /// /// A PRINTER_INFO_4 structure containing minimal printer information, including the name of the printer, the name of the server, /// and whether the printer is remote or local. /// /// /// /// 5 /// A PRINTER_INFO_5 structure containing printer information such as printer attributes and time-out settings. /// /// /// 6 /// A PRINTER_INFO_6 structure specifying the status value of a printer. /// /// /// 7 /// /// A PRINTER_INFO_7 structure. The dwAction member of this structure indicates whether SetPrinter should publish, unpublish, /// re-publish, or update the printer's data in the directory service. /// /// /// /// 8 /// A PRINTER_INFO_8 structure specifying the global default printer settings. /// /// /// 9 /// A PRINTER_INFO_9 structure specifying the per-user default printer settings. /// /// /// /// /// The action to perform. /// /// If the Level parameter is nonzero, set the value of this parameter to zero. In this case, the printer retains its current state /// and the function reconfigures the printer data as specified by the Level and pPrinter parameters. /// /// If the Level parameter is zero, set the value of this parameter to one of the following values. /// /// /// Value /// Meaning /// /// /// PRINTER_CONTROL_PAUSE /// Pause the printer. /// /// /// PRINTER_CONTROL_PURGE /// Delete all print jobs in the printer. /// /// /// PRINTER_CONTROL_RESUME /// Resume a paused printer. /// /// /// PRINTER_CONTROL_SET_STATUS /// Set the printer status. Set the pPrinter parameter to a pointer to a DWORD value that specifies the new printer status. /// /// /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// If Level is 7 and the publish action failed, SetPrinter returns ERROR_IO_PENDING and attempts to complete the /// action in the background. If Level is 7 and the update action failed, SetPrinter returns ERROR_FILE_NOT_FOUND. /// /// /// /// You cannot use SetPrinter to change the default printer. /// /// To modify the current printer settings, call the GetPrinter function to retrieve the current settings into a /// PRINTER_INFO_2 structure, modify the members of that structure as necessary, and then call SetPrinter. /// /// /// The SetPrinter function ignores the pServerName, AveragePPM, Status, and cJobs members of a /// PRINTER_INFO_2 structure. /// /// /// Pausing a printer suspends scheduling of all print jobs for that printer, except for the one print job that may be currently /// printing. Print jobs can be submitted to a paused printer, but no jobs will be scheduled to print on that printer until printing /// is resumed. If a printer is cleared, all print jobs for that printer are deleted, except for the current print job. /// /// /// If you use SetPrinter to modify the default DEVMODE structure for a printer (globally setting the printer /// defaults), you must first call the DocumentProperties function to validate the DEVMODE structure. /// /// /// For the PRINTER_INFO_2 and PRINTER_INFO_3 structures that contain a pointer to a security descriptor, the function /// can set only those components of the security descriptor that the caller has permission to modify. To set particular security /// descriptor components, you must specify the necessary access rights when you call the OpenPrinter or OpenPrinter2 /// function to retrieve a handle to the printer. The following table shows the access rights required to modify the various /// security descriptor components. /// /// /// /// Access permission /// Security descriptor component /// /// /// WRITE_OWNER /// Owner Primary group /// /// /// WRITE_DAC /// Discretionary access-control list (DACL) /// /// /// ACCESS_SYSTEM_SECURITY /// System access-control list (SACL) /// /// /// /// If the security descriptor contains a component that the caller does not have the access right to modify, SetPrinter /// fails. Those components of a security descriptor that you don't want to modify should be NULL or not be present, as /// appropriate. If you do not want to modify the security descriptor, and are calling SetPrinter with a /// PRINTER_INFO_2 structure, set the pSecurityDescriptor member of that structure to NULL. /// /// /// The Internet Connection Firewall (ICF) blocks printer ports by default, but an exception for File and Print Sharing can be /// enabled. If SetPrinter is called by a machine admin, it enables the exception. If it is called by a non-admin and the /// exception has not already been enabled, the call fails. /// /// /// You can use level 7 with the PRINTER_INFO_7 structure to publish, unpublish, or update directory service data for the /// printer. The directory service data for a printer includes all the data stored under the SPLDS_* keys by calls to the /// SetPrinterDataEx function for the printer. Before calling SetPrinter, set the pszObjectGUID member of /// PRINTER_INFO_7 to NULL and set the dwAction member to one of the following values. /// /// /// /// Value /// Description /// /// /// DSPRINT_PUBLISH /// Publishes the directory service data. /// /// /// DSPRINT_REPUBLISH /// /// The directory service data for the printer is unpublished and then published again, refreshing all properties in the published /// printer. Re-publishing also changes the GUID of the published printer. Use this value if you suspect the printer's published /// data has been corrupted. /// /// /// /// DSPRINT_UNPUBLISH /// Unpublishes the directory service data. /// /// /// DSPRINT_UPDATE /// /// Updates the directory service data. This is the same as DSPRINT_PUBLISH, except that SetPrinter fails with ERROR_FILE_NOT_FOUND /// if the printer is not already published. Use DSPRINT_UPDATE to update published properties but not force publishing. Printer /// drivers should always use DSPRINT_UPDATE rather than DSPRINT_PUBLISH. /// /// /// /// DSPRINT_PENDING is not a valid dwAction value for SetPrinter. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/setprinter BOOL SetPrinter( _In_ HANDLE hPrinter, _In_ DWORD Level, _In_ // LPBYTE pPrinter, _In_ DWORD Command ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "ade367c5-20d6-4da9-bb52-ce6768cf7537")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetPrinter(HPRINTER hPrinter, uint Level, IntPtr pPrinter, PRINTER_CONTROL Command = 0); /// /// The SetPrinter function sets the data for a specified printer or sets the state of the specified printer by pausing /// printing, resuming printing, or clearing all print jobs. /// /// /// A handle to the printer. Use the OpenPrinter, OpenPrinter2, or AddPrinter function to retrieve a printer handle. /// /// /// The action to perform. Set the value of this parameter to one of the following values. /// /// /// Value /// Meaning /// /// /// PRINTER_CONTROL_PAUSE /// Pause the printer. /// /// /// PRINTER_CONTROL_PURGE /// Delete all print jobs in the printer. /// /// /// PRINTER_CONTROL_RESUME /// Resume a paused printer. /// /// /// PRINTER_CONTROL_SET_STATUS /// /// Set the printer status. Set the pPrinter parameter to a pointer to a DWORD value that specifies the new printer status. /// /// /// /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/setprinter BOOL SetPrinter( _In_ HANDLE hPrinter, _In_ DWORD Level, _In_ // LPBYTE pPrinter, _In_ DWORD Command ); [PInvokeData("winspool.h", MSDNShortId = "ade367c5-20d6-4da9-bb52-ce6768cf7537")] public static bool SetPrinter(HPRINTER hPrinter, PRINTER_CONTROL Command) => SetPrinter(hPrinter, 0, default, Command); /// /// The SetPrinter function sets the data for a specified printer or sets the state of the specified printer by pausing /// printing, resuming printing, or clearing all print jobs. /// /// The type of the structure used in . /// /// A handle to the printer. Use the OpenPrinter, OpenPrinter2, or AddPrinter function to retrieve a printer handle. /// /// /// /// A pointer to a buffer containing data to set for the printer, or containing information for the command specified by the Command /// parameter. The type of data in the buffer is determined by the value of Level. /// /// /// /// Level /// Structure /// /// /// 0 /// /// If the Command parameter is PRINTER_CONTROL_SET_STATUS, pPrinter must contain a DWORD value that specifies the new printer /// status to set. For a list of the possible status values, see the Status member of the PRINTER_INFO_2 structure. Note that /// PRINTER_STATUS_PAUSED and PRINTER_STATUS_PENDING_DELETION are not valid status values to set. If Level is 0, but the Command /// parameter is not PRINTER_CONTROL_SET_STATUS, pPrinter must be NULL. /// /// /// /// 2 /// A PRINTER_INFO_2 structure containing detailed information about the printer. /// /// /// 3 /// A PRINTER_INFO_3 structure containing the printer's security information. /// /// /// 4 /// /// A PRINTER_INFO_4 structure containing minimal printer information, including the name of the printer, the name of the server, /// and whether the printer is remote or local. /// /// /// /// 5 /// A PRINTER_INFO_5 structure containing printer information such as printer attributes and time-out settings. /// /// /// 6 /// A PRINTER_INFO_6 structure specifying the status value of a printer. /// /// /// 7 /// /// A PRINTER_INFO_7 structure. The dwAction member of this structure indicates whether SetPrinter should publish, unpublish, /// re-publish, or update the printer's data in the directory service. /// /// /// /// 8 /// A PRINTER_INFO_8 structure specifying the global default printer settings. /// /// /// 9 /// A PRINTER_INFO_9 structure specifying the per-user default printer settings. /// /// /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// If Level is 7 and the publish action failed, SetPrinter returns ERROR_IO_PENDING and attempts to complete the /// action in the background. If Level is 7 and the update action failed, SetPrinter returns ERROR_FILE_NOT_FOUND. /// /// /// /// /// You cannot use SetPrinter to change the default printer. /// /// To modify the current printer settings, call the GetPrinter function to retrieve the current settings into a /// PRINTER_INFO_2 structure, modify the members of that structure as necessary, and then call SetPrinter. /// /// /// The SetPrinter function ignores the pServerName, AveragePPM, Status, and cJobs members of a /// PRINTER_INFO_2 structure. /// /// /// Pausing a printer suspends scheduling of all print jobs for that printer, except for the one print job that may be currently /// printing. Print jobs can be submitted to a paused printer, but no jobs will be scheduled to print on that printer until printing /// is resumed. If a printer is cleared, all print jobs for that printer are deleted, except for the current print job. /// /// /// If you use SetPrinter to modify the default DEVMODE structure for a printer (globally setting the printer /// defaults), you must first call the DocumentProperties function to validate the DEVMODE structure. /// /// /// For the PRINTER_INFO_2 and PRINTER_INFO_3 structures that contain a pointer to a security descriptor, the function /// can set only those components of the security descriptor that the caller has permission to modify. To set particular security /// descriptor components, you must specify the necessary access rights when you call the OpenPrinter or OpenPrinter2 /// function to retrieve a handle to the printer. The following table shows the access rights required to modify the various /// security descriptor components. /// /// /// /// Access permission /// Security descriptor component /// /// /// WRITE_OWNER /// Owner Primary group /// /// /// WRITE_DAC /// Discretionary access-control list (DACL) /// /// /// ACCESS_SYSTEM_SECURITY /// System access-control list (SACL) /// /// /// /// If the security descriptor contains a component that the caller does not have the access right to modify, SetPrinter /// fails. Those components of a security descriptor that you don't want to modify should be NULL or not be present, as /// appropriate. If you do not want to modify the security descriptor, and are calling SetPrinter with a /// PRINTER_INFO_2 structure, set the pSecurityDescriptor member of that structure to NULL. /// /// /// The Internet Connection Firewall (ICF) blocks printer ports by default, but an exception for File and Print Sharing can be /// enabled. If SetPrinter is called by a machine admin, it enables the exception. If it is called by a non-admin and the /// exception has not already been enabled, the call fails. /// /// /// You can use level 7 with the PRINTER_INFO_7 structure to publish, unpublish, or update directory service data for the /// printer. The directory service data for a printer includes all the data stored under the SPLDS_* keys by calls to the /// SetPrinterDataEx function for the printer. Before calling SetPrinter, set the pszObjectGUID member of /// PRINTER_INFO_7 to NULL and set the dwAction member to one of the following values. /// /// /// /// Value /// Description /// /// /// DSPRINT_PUBLISH /// Publishes the directory service data. /// /// /// DSPRINT_REPUBLISH /// /// The directory service data for the printer is unpublished and then published again, refreshing all properties in the published /// printer. Re-publishing also changes the GUID of the published printer. Use this value if you suspect the printer's published /// data has been corrupted. /// /// /// /// DSPRINT_UNPUBLISH /// Unpublishes the directory service data. /// /// /// DSPRINT_UPDATE /// /// Updates the directory service data. This is the same as DSPRINT_PUBLISH, except that SetPrinter fails with ERROR_FILE_NOT_FOUND /// if the printer is not already published. Use DSPRINT_UPDATE to update published properties but not force publishing. Printer /// drivers should always use DSPRINT_UPDATE rather than DSPRINT_PUBLISH. /// /// /// /// DSPRINT_PENDING is not a valid dwAction value for SetPrinter. /// [PInvokeData("winspool.h", MSDNShortId = "ade367c5-20d6-4da9-bb52-ce6768cf7537")] public static bool SetPrinter(HPRINTER hPrinter, in T pPrinter) where T : struct { if (!TryGetLevel("PRINTER_INFO_", out var lvl)) throw new ArgumentException($"{nameof(SetPrinter)} cannot process a structure of type {typeof(T).Name}."); using var mem = SafeCoTaskMemHandle.CreateFromStructure(pPrinter); return SetPrinter(hPrinter, lvl, mem); } /// /// The SetPrinterData function sets the configuration data for a printer or print server. /// /// To specify the registry key under which to store the data, call the SetPrinterDataEx function. Calling /// SetPrinterData is equivalent to calling the SetPrinterDataEx function with the pKeyName parameter set to "PrinterDriverData". /// /// /// /// A handle to the printer or print server for which the function sets configuration data. Use the OpenPrinter, /// OpenPrinter2, or AddPrinter function to retrieve a printer handle. /// /// /// A pointer to a null-terminated string that identifies the data to set. /// For printers, this string is the name of a registry value under the printer's "PrinterDriverData" key in the registry. /// For print servers, this string is one of the predefined strings listed in the following Remarks section. /// /// /// A code that indicates the type of data that the pData parameter points to. For a list of the possible type codes, see Registry /// Value Types. /// /// A pointer to an array of bytes that contains the printer configuration data. /// The size, in bytes, of the array. /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is an error value. /// /// /// To retrieve existing configuration data for a printer, call the GetPrinterDataEx or GetPrinterData function. /// If hPrinter is a handle to a print server, pValueName can specify one of the following predefined values. /// /// /// Value /// Comments /// /// /// SPLREG_ALLOW_USER_MANAGEFORMS /// Windows XP with Service Pack 2 (SP2) and later Windows Server 2003 with Service Pack 1 (SP1) and later /// /// /// SPLREG_BEEP_ENABLED /// /// /// /// SPLREG_DEFAULT_SPOOL_DIRECTORY /// /// /// /// SPLREG_EVENT_LOG /// /// /// /// SPLREG_NET_POPUP /// Not supported in Windows Server 2003 and later /// /// /// SPLREG_PORT_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_PORT_THREAD_PRIORITY /// /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_GROUPS /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_TIME_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_MAX_OBJECTS_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_IDLE_TIMEOUT /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_EXECUTION_POLICY /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_OVERRIDE_POLICY /// Windows 7 and later /// /// /// SPLREG_RETRY_POPUP /// /// On successful return, pData contains 1 if server is set to retry pop-up windows for all jobs, or 0 if server does not retry /// pop-up windows for all jobs. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_WEBSHAREMGMT /// Windows Server 2003 and later /// /// /// The following values of pValueName determine the pool printing behavior when an error occurs. /// /// /// Value /// Comments /// /// /// SPLREG_RESTART_JOB_ON_POOL_ERROR /// /// The value of pData indicates the time, in seconds, when a job is restarted on another port after an error occurs. This setting /// is used with SPLREG_RESTART_JOB_ON_POOL_ENABLED. /// /// /// /// SPLREG_RESTART_JOB_ON_POOL_ENABLED /// A nonzero value in pData indicates that SPLREG_RESTART_JOB_ON_POOL_ERROR is enabled. /// /// /// /// The time specified in SPLREG_RESTART_JOB_ON_POOL_ERROR is a minimum time. The actual time can be longer, depending on the /// following port monitor settings, which are registry values under this registry key: /// /// HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors\<MonitorName>\Ports /// Call the RegSetValueEx function to set these values. /// /// /// Port monitor setting /// Data type /// Meaning /// /// /// StatusUpdateEnabled /// REG_DWORD /// If a nonzero value, enables the port monitor to update the spooler with the port status. /// /// /// StatusUpdateInterval /// REG_DWORD /// Specifies the interval, in minutes, when the port monitor updates the spooler with the port status. /// /// /// /// In Windows 7 and later versions of Windows, print jobs that are sent to a print server are rendered on the client by default. /// Client-side rendering of a print jobs can be configured for each printer by setting the following values in pValueName. /// /// /// /// Setting /// Data type /// Description /// /// /// EMFDespoolingSetting /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, enables the default client-side rendering of print jobs. A value /// of 1 disables client-side rendering of print jobs. /// /// /// /// ForceClientSideRendering /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, causes the print jobs to be rendered on the client. If a print /// job cannot be rendered on the client, it will be rendered on the server. If a print job cannot be rendered on the server, it /// will fail. A value of 1 will render print jobs on the client. If a print job cannot be rendered on the client, it will fail. /// /// /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/setprinterdata DWORD SetPrinterData( _In_ HANDLE hPrinter, _In_ LPTSTR // pValueName, _In_ DWORD Type, _In_ LPBYTE pData, _In_ DWORD cbData ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "16072de9-98fb-4ada-8216-180b64cf44c8")] public static extern Win32Error SetPrinterData(HPRINTER hPrinter, string pValueName, REG_VALUE_TYPE Type, IntPtr pData, uint cbData); /// /// The SetPrinterData function sets the configuration data for a printer or print server. /// /// To specify the registry key under which to store the data, call the SetPrinterDataEx function. Calling /// SetPrinterData is equivalent to calling the SetPrinterDataEx function with the pKeyName parameter set to "PrinterDriverData". /// /// /// /// A handle to the printer or print server for which the function sets configuration data. Use the OpenPrinter, /// OpenPrinter2, or AddPrinter function to retrieve a printer handle. /// /// /// A pointer to a null-terminated string that identifies the data to set. /// For printers, this string is the name of a registry value under the printer's "PrinterDriverData" key in the registry. /// For print servers, this string is one of the predefined strings listed in the following Remarks section. /// /// /// A code that indicates the type of data that the pData parameter points to. For a list of the possible type codes, see Registry /// Value Types. /// /// A pointer to an array of bytes that contains the printer configuration data. /// The size, in bytes, of the array. /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is an error value. /// /// /// To retrieve existing configuration data for a printer, call the GetPrinterDataEx or GetPrinterData function. /// If hPrinter is a handle to a print server, pValueName can specify one of the following predefined values. /// /// /// Value /// Comments /// /// /// SPLREG_ALLOW_USER_MANAGEFORMS /// Windows XP with Service Pack 2 (SP2) and later Windows Server 2003 with Service Pack 1 (SP1) and later /// /// /// SPLREG_BEEP_ENABLED /// /// /// /// SPLREG_DEFAULT_SPOOL_DIRECTORY /// /// /// /// SPLREG_EVENT_LOG /// /// /// /// SPLREG_NET_POPUP /// Not supported in Windows Server 2003 and later /// /// /// SPLREG_PORT_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_PORT_THREAD_PRIORITY /// /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_GROUPS /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_TIME_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_MAX_OBJECTS_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_IDLE_TIMEOUT /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_EXECUTION_POLICY /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_OVERRIDE_POLICY /// Windows 7 and later /// /// /// SPLREG_RETRY_POPUP /// /// On successful return, pData contains 1 if server is set to retry pop-up windows for all jobs, or 0 if server does not retry /// pop-up windows for all jobs. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_WEBSHAREMGMT /// Windows Server 2003 and later /// /// /// The following values of pValueName determine the pool printing behavior when an error occurs. /// /// /// Value /// Comments /// /// /// SPLREG_RESTART_JOB_ON_POOL_ERROR /// /// The value of pData indicates the time, in seconds, when a job is restarted on another port after an error occurs. This setting /// is used with SPLREG_RESTART_JOB_ON_POOL_ENABLED. /// /// /// /// SPLREG_RESTART_JOB_ON_POOL_ENABLED /// A nonzero value in pData indicates that SPLREG_RESTART_JOB_ON_POOL_ERROR is enabled. /// /// /// /// The time specified in SPLREG_RESTART_JOB_ON_POOL_ERROR is a minimum time. The actual time can be longer, depending on the /// following port monitor settings, which are registry values under this registry key: /// /// HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors\<MonitorName>\Ports /// Call the RegSetValueEx function to set these values. /// /// /// Port monitor setting /// Data type /// Meaning /// /// /// StatusUpdateEnabled /// REG_DWORD /// If a nonzero value, enables the port monitor to update the spooler with the port status. /// /// /// StatusUpdateInterval /// REG_DWORD /// Specifies the interval, in minutes, when the port monitor updates the spooler with the port status. /// /// /// /// In Windows 7 and later versions of Windows, print jobs that are sent to a print server are rendered on the client by default. /// Client-side rendering of a print jobs can be configured for each printer by setting the following values in pValueName. /// /// /// /// Setting /// Data type /// Description /// /// /// EMFDespoolingSetting /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, enables the default client-side rendering of print jobs. A value /// of 1 disables client-side rendering of print jobs. /// /// /// /// ForceClientSideRendering /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, causes the print jobs to be rendered on the client. If a print /// job cannot be rendered on the client, it will be rendered on the server. If a print job cannot be rendered on the server, it /// will fail. A value of 1 will render print jobs on the client. If a print job cannot be rendered on the client, it will fail. /// /// /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/setprinterdata DWORD SetPrinterData( _In_ HANDLE hPrinter, _In_ LPTSTR // pValueName, _In_ DWORD Type, _In_ LPBYTE pData, _In_ DWORD cbData ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "16072de9-98fb-4ada-8216-180b64cf44c8")] public static extern Win32Error SetPrinterData(HPRINTER hPrinter, string pValueName, REG_VALUE_TYPE Type, byte[] pData, int cbData); /// /// The SetPrinterData function sets the configuration data for a printer or print server. /// /// To specify the registry key under which to store the data, call the SetPrinterDataEx function. Calling /// SetPrinterData is equivalent to calling the SetPrinterDataEx function with the pKeyName parameter set to "PrinterDriverData". /// /// /// /// A handle to the printer or print server for which the function sets configuration data. Use the OpenPrinter, /// OpenPrinter2, or AddPrinter function to retrieve a printer handle. /// /// /// A pointer to a null-terminated string that identifies the data to set. /// For printers, this string is the name of a registry value under the printer's "PrinterDriverData" key in the registry. /// For print servers, this string is one of the predefined strings listed in the following Remarks section. /// /// A pointer to an array of bytes that contains the printer configuration data. /// /// A code that indicates the type of data that the pData parameter points to. For a list of the possible type codes, see Registry /// Value Types. /// /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is an error value. /// /// /// To retrieve existing configuration data for a printer, call the GetPrinterDataEx or GetPrinterData function. /// If hPrinter is a handle to a print server, pValueName can specify one of the following predefined values. /// /// /// Value /// Comments /// /// /// SPLREG_ALLOW_USER_MANAGEFORMS /// Windows XP with Service Pack 2 (SP2) and later Windows Server 2003 with Service Pack 1 (SP1) and later /// /// /// SPLREG_BEEP_ENABLED /// /// /// /// SPLREG_DEFAULT_SPOOL_DIRECTORY /// /// /// /// SPLREG_EVENT_LOG /// /// /// /// SPLREG_NET_POPUP /// Not supported in Windows Server 2003 and later /// /// /// SPLREG_PORT_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_PORT_THREAD_PRIORITY /// /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_GROUPS /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_TIME_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_MAX_OBJECTS_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_IDLE_TIMEOUT /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_EXECUTION_POLICY /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_OVERRIDE_POLICY /// Windows 7 and later /// /// /// SPLREG_RETRY_POPUP /// /// On successful return, pData contains 1 if server is set to retry pop-up windows for all jobs, or 0 if server does not retry /// pop-up windows for all jobs. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_WEBSHAREMGMT /// Windows Server 2003 and later /// /// /// The following values of pValueName determine the pool printing behavior when an error occurs. /// /// /// Value /// Comments /// /// /// SPLREG_RESTART_JOB_ON_POOL_ERROR /// /// The value of pData indicates the time, in seconds, when a job is restarted on another port after an error occurs. This setting /// is used with SPLREG_RESTART_JOB_ON_POOL_ENABLED. /// /// /// /// SPLREG_RESTART_JOB_ON_POOL_ENABLED /// A nonzero value in pData indicates that SPLREG_RESTART_JOB_ON_POOL_ERROR is enabled. /// /// /// /// The time specified in SPLREG_RESTART_JOB_ON_POOL_ERROR is a minimum time. The actual time can be longer, depending on the /// following port monitor settings, which are registry values under this registry key: /// /// HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors\<MonitorName>\Ports /// Call the RegSetValueEx function to set these values. /// /// /// Port monitor setting /// Data type /// Meaning /// /// /// StatusUpdateEnabled /// REG_DWORD /// If a nonzero value, enables the port monitor to update the spooler with the port status. /// /// /// StatusUpdateInterval /// REG_DWORD /// Specifies the interval, in minutes, when the port monitor updates the spooler with the port status. /// /// /// /// In Windows 7 and later versions of Windows, print jobs that are sent to a print server are rendered on the client by default. /// Client-side rendering of a print jobs can be configured for each printer by setting the following values in pValueName. /// /// /// /// Setting /// Data type /// Description /// /// /// EMFDespoolingSetting /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, enables the default client-side rendering of print jobs. A value /// of 1 disables client-side rendering of print jobs. /// /// /// /// ForceClientSideRendering /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, causes the print jobs to be rendered on the client. If a print /// job cannot be rendered on the client, it will be rendered on the server. If a print job cannot be rendered on the server, it /// will fail. A value of 1 will render print jobs on the client. If a print job cannot be rendered on the client, it will fail. /// /// /// /// [PInvokeData("winspool.h", MSDNShortId = "16072de9-98fb-4ada-8216-180b64cf44c8")] public static Win32Error SetPrinterData(HPRINTER hPrinter, string pValueName, object pData, REG_VALUE_TYPE type = 0) { return InlineSetPrinterData(SetData, hPrinter, null, pValueName, pData, type); static Win32Error SetData(HPRINTER p1, string p2, string p3, REG_VALUE_TYPE p4, IntPtr p5, uint p6) => SetPrinterData(p1, p3, p4, p5, p6); } /// /// The SetPrinterDataEx function sets the configuration data for a printer or print server. The function stores the /// configuration data under the printer's registry key. /// /// /// A handle to the printer or print server for which the function sets configuration data. Use the OpenPrinter, /// OpenPrinter2, or AddPrinter function to retrieve a printer handle. /// /// /// /// A pointer to a null-terminated string that specifies the key containing the value to set. If the specified key or subkeys do not /// exist, the function creates them. /// /// /// To store configuration data that can be published in the directory service (DS), specify one of the following predefined /// registry keys. /// /// /// /// Value /// Meaning /// /// /// SPLDS_DRIVER_KEY /// Printer drivers use this key to store driver properties. /// /// /// SPLDS_SPOOLER_KEY /// Reserved. Used only by the print spooler to store internal spooler properties. /// /// /// SPLDS_USER_KEY /// Applications use this key to store printer properties such as printer asset numbers. /// /// /// /// Values that are stored under the SPLDS_USER_KEY key are published in the directory service only if there is a corresponding /// property in the schema. A domain administrator must create the property if it doesn't already exist. To publish a user-defined /// property after you use SetPrinterDataEx to add or change a value, call SetPrinter with Level = 7 and with the /// dwAction member of PRINTER_INFO_7 set to DSPRINT_UPDATE. /// /// /// You can specify other keys to store non-DS configuration data. Use the backslash ( \ ) character as a delimiter to specify a /// path that has one or more subkeys. /// /// If hPrinter is a handle to a printer and pKeyName is NULL or an empty string, SetPrinterDataEx returns ERROR_INVALID_PARAMETER. /// If hPrinter is a handle to a print server, pKeyName is ignored. /// Do not use SPLDS_SPOOLER_KEY. To change the spooler printer properties, use SetPrinter with Level = 2. /// /// /// A pointer to a null-terminated string that identifies the data to set. /// For printers, this string specifies the name of a value under the pKeyName key. /// For print servers, this string is one of the predefined strings listed in the following Remarks section. /// /// /// /// A code indicating the type of data pointed to by the pData parameter. For a list of the possible type codes, see Registry Value Types. /// /// /// If pKeyName specifies one of the predefined directory service keys, Type must be REG_SZ, REG_MULTI_SZ, /// REG_DWORD, or REG_BINARY. If REG_BINARY is used, cbData must be equal to 1, and the directory service /// treats the data as a Boolean value. /// /// /// A pointer to a buffer that contains the printer configuration data. /// The size, in bytes, of the array. /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is an error value. /// /// /// To retrieve existing configuration data for a printer or print spooler, call the GetPrinterDataEx function. /// /// Calling SetPrinterDataEx with the pKeyName parameter set to "PrinterDriverData" is equivalent to calling the /// SetPrinterData function. /// /// If hPrinter is a handle to a print server, pValueName can specify one of the following predefined values. /// /// /// Value /// Comments /// /// /// SPLREG_ALLOW_USER_MANAGEFORMS /// Windows XP with Service Pack 2 (SP2) and later Windows Server 2003 with Service Pack 1 (SP1) and later /// /// /// SPLREG_BEEP_ENABLED /// /// /// /// SPLREG_DEFAULT_SPOOL_DIRECTORY /// /// /// /// SPLREG_EVENT_LOG /// /// /// /// SPLREG_NET_POPUP /// Not supported in Windows Server 2003 and later /// /// /// SPLREG_PORT_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_PORT_THREAD_PRIORITY /// /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_GROUPS /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_TIME_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_MAX_OBJECTS_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_IDLE_TIMEOUT /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_EXECUTION_POLICY /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_OVERRIDE_POLICY /// Windows 7 and later /// /// /// SPLREG_RETRY_POPUP /// /// On successful return, pData contains 1 if server is set to retry pop-up windows for all jobs, or 0 if server does not retry /// pop-up windows for all jobs. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_WEBSHAREMGMT /// Windows Server 2003 and later /// /// /// Passing one of the following predefined values as pValueName sets the pool printing behavior when an error occurs. /// /// /// Value /// Comments /// /// /// SPLREG_RESTART_JOB_ON_POOL_ERROR /// /// The value of pData indicates the time, in seconds, when a job is restarted on another port after an error occurs. This setting /// is used with SPLREG_RESTART_JOB_ON_POOL_ENABLED. /// /// /// /// SPLREG_RESTART_JOB_ON_POOL_ENABLED /// A nonzero value in pData indicates that SPLREG_RESTART_JOB_ON_POOL_ERROR is enabled. /// /// /// /// The time specified in SPLREG_RESTART_JOB_ON_POOL_ERROR is a minimum time. The actual time can be longer, depending on the /// following port monitor settings, which are registry values under this registry key: /// /// HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors\<MonitorName>\Ports /// Call the RegSetValueEx function to set these values. /// /// /// Port monitor setting /// Data type /// Meaning /// /// /// StatusUpdateEnabled /// REG_DWORD /// If a nonzero value, enables the port monitor to update the spooler with the port status. /// /// /// StatusUpdateInterval /// REG_DWORD /// Specifies the interval, in minutes, when the port monitor updates the spooler with the port status. /// /// /// /// To ensure that the spooler redirects jobs to the next available printer in the pool (when the print job is not printed within /// the set time), the port monitor must support SNMP and the network ports in the pool must be configured as "SNMP status enabled." /// The port monitor that supports SNMP is Standard TCP/IP port monitor. /// /// /// In Windows 7 and later versions of Windows, print jobs that are sent to a print server are rendered on the client by default. /// Client-side rendering of print jobs can be configured by setting pKeyName to "PrinterDriverData" and pValueName to the setting /// value in the following table. /// /// /// /// Setting /// Data type /// Description /// /// /// EMFDespoolingSetting /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, enables the default client-side rendering of print jobs. A value /// of 1 disables client-side rendering of print jobs. /// /// /// /// ForceClientSideRendering /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, will cause the print jobs to be rendered on the client. If a /// print job cannot be rendered on the client, it will be rendered on the server. If a print job cannot be rendered on the server, /// it will fail. A value of 1 will render print jobs on the client. If a print job cannot be rendered on the client, it will fail. /// /// /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/setprinterdataex DWORD SetPrinterDataEx( _In_ HANDLE hPrinter, _In_ // LPCTSTR pKeyName, _In_ LPCTSTR pValueName, _In_ DWORD Type, _In_ LPBYTE pData, _In_ DWORD cbData ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "b7faadfc-1c81-4ddf-8fe5-68f4cc0376f1")] public static extern Win32Error SetPrinterDataEx(HPRINTER hPrinter, string pKeyName, string pValueName, REG_VALUE_TYPE Type, IntPtr pData, uint cbData); /// /// The SetPrinterDataEx function sets the configuration data for a printer or print server. The function stores the /// configuration data under the printer's registry key. /// /// /// A handle to the printer or print server for which the function sets configuration data. Use the OpenPrinter, /// OpenPrinter2, or AddPrinter function to retrieve a printer handle. /// /// /// /// A pointer to a null-terminated string that specifies the key containing the value to set. If the specified key or subkeys do not /// exist, the function creates them. /// /// /// To store configuration data that can be published in the directory service (DS), specify one of the following predefined /// registry keys. /// /// /// /// Value /// Meaning /// /// /// SPLDS_DRIVER_KEY /// Printer drivers use this key to store driver properties. /// /// /// SPLDS_SPOOLER_KEY /// Reserved. Used only by the print spooler to store internal spooler properties. /// /// /// SPLDS_USER_KEY /// Applications use this key to store printer properties such as printer asset numbers. /// /// /// /// Values that are stored under the SPLDS_USER_KEY key are published in the directory service only if there is a corresponding /// property in the schema. A domain administrator must create the property if it doesn't already exist. To publish a user-defined /// property after you use SetPrinterDataEx to add or change a value, call SetPrinter with Level = 7 and with the /// dwAction member of PRINTER_INFO_7 set to DSPRINT_UPDATE. /// /// /// You can specify other keys to store non-DS configuration data. Use the backslash ( \ ) character as a delimiter to specify a /// path that has one or more subkeys. /// /// If hPrinter is a handle to a printer and pKeyName is NULL or an empty string, SetPrinterDataEx returns ERROR_INVALID_PARAMETER. /// If hPrinter is a handle to a print server, pKeyName is ignored. /// Do not use SPLDS_SPOOLER_KEY. To change the spooler printer properties, use SetPrinter with Level = 2. /// /// /// A pointer to a null-terminated string that identifies the data to set. /// For printers, this string specifies the name of a value under the pKeyName key. /// For print servers, this string is one of the predefined strings listed in the following Remarks section. /// /// /// /// A code indicating the type of data pointed to by the pData parameter. For a list of the possible type codes, see Registry Value Types. /// /// /// If pKeyName specifies one of the predefined directory service keys, Type must be REG_SZ, REG_MULTI_SZ, /// REG_DWORD, or REG_BINARY. If REG_BINARY is used, cbData must be equal to 1, and the directory service /// treats the data as a Boolean value. /// /// /// A pointer to a buffer that contains the printer configuration data. /// The size, in bytes, of the array. /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is an error value. /// /// /// To retrieve existing configuration data for a printer or print spooler, call the GetPrinterDataEx function. /// /// Calling SetPrinterDataEx with the pKeyName parameter set to "PrinterDriverData" is equivalent to calling the /// SetPrinterData function. /// /// If hPrinter is a handle to a print server, pValueName can specify one of the following predefined values. /// /// /// Value /// Comments /// /// /// SPLREG_ALLOW_USER_MANAGEFORMS /// Windows XP with Service Pack 2 (SP2) and later Windows Server 2003 with Service Pack 1 (SP1) and later /// /// /// SPLREG_BEEP_ENABLED /// /// /// /// SPLREG_DEFAULT_SPOOL_DIRECTORY /// /// /// /// SPLREG_EVENT_LOG /// /// /// /// SPLREG_NET_POPUP /// Not supported in Windows Server 2003 and later /// /// /// SPLREG_PORT_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_PORT_THREAD_PRIORITY /// /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_GROUPS /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_TIME_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_MAX_OBJECTS_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_IDLE_TIMEOUT /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_EXECUTION_POLICY /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_OVERRIDE_POLICY /// Windows 7 and later /// /// /// SPLREG_RETRY_POPUP /// /// On successful return, pData contains 1 if server is set to retry pop-up windows for all jobs, or 0 if server does not retry /// pop-up windows for all jobs. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_WEBSHAREMGMT /// Windows Server 2003 and later /// /// /// Passing one of the following predefined values as pValueName sets the pool printing behavior when an error occurs. /// /// /// Value /// Comments /// /// /// SPLREG_RESTART_JOB_ON_POOL_ERROR /// /// The value of pData indicates the time, in seconds, when a job is restarted on another port after an error occurs. This setting /// is used with SPLREG_RESTART_JOB_ON_POOL_ENABLED. /// /// /// /// SPLREG_RESTART_JOB_ON_POOL_ENABLED /// A nonzero value in pData indicates that SPLREG_RESTART_JOB_ON_POOL_ERROR is enabled. /// /// /// /// The time specified in SPLREG_RESTART_JOB_ON_POOL_ERROR is a minimum time. The actual time can be longer, depending on the /// following port monitor settings, which are registry values under this registry key: /// /// HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors\<MonitorName>\Ports /// Call the RegSetValueEx function to set these values. /// /// /// Port monitor setting /// Data type /// Meaning /// /// /// StatusUpdateEnabled /// REG_DWORD /// If a nonzero value, enables the port monitor to update the spooler with the port status. /// /// /// StatusUpdateInterval /// REG_DWORD /// Specifies the interval, in minutes, when the port monitor updates the spooler with the port status. /// /// /// /// To ensure that the spooler redirects jobs to the next available printer in the pool (when the print job is not printed within /// the set time), the port monitor must support SNMP and the network ports in the pool must be configured as "SNMP status enabled." /// The port monitor that supports SNMP is Standard TCP/IP port monitor. /// /// /// In Windows 7 and later versions of Windows, print jobs that are sent to a print server are rendered on the client by default. /// Client-side rendering of print jobs can be configured by setting pKeyName to "PrinterDriverData" and pValueName to the setting /// value in the following table. /// /// /// /// Setting /// Data type /// Description /// /// /// EMFDespoolingSetting /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, enables the default client-side rendering of print jobs. A value /// of 1 disables client-side rendering of print jobs. /// /// /// /// ForceClientSideRendering /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, will cause the print jobs to be rendered on the client. If a /// print job cannot be rendered on the client, it will be rendered on the server. If a print job cannot be rendered on the server, /// it will fail. A value of 1 will render print jobs on the client. If a print job cannot be rendered on the client, it will fail. /// /// /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/setprinterdataex DWORD SetPrinterDataEx( _In_ HANDLE hPrinter, _In_ // LPCTSTR pKeyName, _In_ LPCTSTR pValueName, _In_ DWORD Type, _In_ LPBYTE pData, _In_ DWORD cbData ); [DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "b7faadfc-1c81-4ddf-8fe5-68f4cc0376f1")] public static extern Win32Error SetPrinterDataEx(HPRINTER hPrinter, string pKeyName, string pValueName, REG_VALUE_TYPE Type, byte[] pData, uint cbData); /// /// The SetPrinterDataEx function sets the configuration data for a printer or print server. The function stores the /// configuration data under the printer's registry key. /// /// /// A handle to the printer or print server for which the function sets configuration data. Use the OpenPrinter, /// OpenPrinter2, or AddPrinter function to retrieve a printer handle. /// /// /// /// A pointer to a null-terminated string that specifies the key containing the value to set. If the specified key or subkeys do not /// exist, the function creates them. /// /// /// To store configuration data that can be published in the directory service (DS), specify one of the following predefined /// registry keys. /// /// /// /// Value /// Meaning /// /// /// SPLDS_DRIVER_KEY /// Printer drivers use this key to store driver properties. /// /// /// SPLDS_SPOOLER_KEY /// Reserved. Used only by the print spooler to store internal spooler properties. /// /// /// SPLDS_USER_KEY /// Applications use this key to store printer properties such as printer asset numbers. /// /// /// /// Values that are stored under the SPLDS_USER_KEY key are published in the directory service only if there is a corresponding /// property in the schema. A domain administrator must create the property if it doesn't already exist. To publish a user-defined /// property after you use SetPrinterDataEx to add or change a value, call SetPrinter with Level = 7 and with the /// dwAction member of PRINTER_INFO_7 set to DSPRINT_UPDATE. /// /// /// You can specify other keys to store non-DS configuration data. Use the backslash ( \ ) character as a delimiter to specify a /// path that has one or more subkeys. /// /// If hPrinter is a handle to a printer and pKeyName is NULL or an empty string, SetPrinterDataEx returns ERROR_INVALID_PARAMETER. /// If hPrinter is a handle to a print server, pKeyName is ignored. /// Do not use SPLDS_SPOOLER_KEY. To change the spooler printer properties, use SetPrinter with Level = 2. /// /// /// A pointer to a null-terminated string that identifies the data to set. /// For printers, this string specifies the name of a value under the pKeyName key. /// For print servers, this string is one of the predefined strings listed in the following Remarks section. /// /// A pointer to a buffer that contains the printer configuration data. /// /// /// A code indicating the type of data pointed to by the pData parameter. For a list of the possible type codes, see Registry Value Types. /// /// /// If pKeyName specifies one of the predefined directory service keys, Type must be REG_SZ, REG_MULTI_SZ, /// REG_DWORD, or REG_BINARY. If REG_BINARY is used, cbData must be equal to 1, and the directory service /// treats the data as a Boolean value. /// /// /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the return value is an error value. /// /// /// To retrieve existing configuration data for a printer or print spooler, call the GetPrinterDataEx function. /// /// Calling SetPrinterDataEx with the pKeyName parameter set to "PrinterDriverData" is equivalent to calling the /// SetPrinterData function. /// /// If hPrinter is a handle to a print server, pValueName can specify one of the following predefined values. /// /// /// Value /// Comments /// /// /// SPLREG_ALLOW_USER_MANAGEFORMS /// Windows XP with Service Pack 2 (SP2) and later Windows Server 2003 with Service Pack 1 (SP1) and later /// /// /// SPLREG_BEEP_ENABLED /// /// /// /// SPLREG_DEFAULT_SPOOL_DIRECTORY /// /// /// /// SPLREG_EVENT_LOG /// /// /// /// SPLREG_NET_POPUP /// Not supported in Windows Server 2003 and later /// /// /// SPLREG_PORT_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_PORT_THREAD_PRIORITY /// /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_GROUPS /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_TIME_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_MAX_OBJECTS_BEFORE_RECYCLE /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_IDLE_TIMEOUT /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_EXECUTION_POLICY /// Windows 7 and later /// /// /// SPLREG_PRINT_DRIVER_ISOLATION_OVERRIDE_POLICY /// Windows 7 and later /// /// /// SPLREG_RETRY_POPUP /// /// On successful return, pData contains 1 if server is set to retry pop-up windows for all jobs, or 0 if server does not retry /// pop-up windows for all jobs. Not supported in Windows Server 2003 and later /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY /// /// /// /// SPLREG_SCHEDULER_THREAD_PRIORITY_DEFAULT /// /// /// /// SPLREG_WEBSHAREMGMT /// Windows Server 2003 and later /// /// /// Passing one of the following predefined values as pValueName sets the pool printing behavior when an error occurs. /// /// /// Value /// Comments /// /// /// SPLREG_RESTART_JOB_ON_POOL_ERROR /// /// The value of pData indicates the time, in seconds, when a job is restarted on another port after an error occurs. This setting /// is used with SPLREG_RESTART_JOB_ON_POOL_ENABLED. /// /// /// /// SPLREG_RESTART_JOB_ON_POOL_ENABLED /// A nonzero value in pData indicates that SPLREG_RESTART_JOB_ON_POOL_ERROR is enabled. /// /// /// /// The time specified in SPLREG_RESTART_JOB_ON_POOL_ERROR is a minimum time. The actual time can be longer, depending on the /// following port monitor settings, which are registry values under this registry key: /// /// HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors\<MonitorName>\Ports /// Call the RegSetValueEx function to set these values. /// /// /// Port monitor setting /// Data type /// Meaning /// /// /// StatusUpdateEnabled /// REG_DWORD /// If a nonzero value, enables the port monitor to update the spooler with the port status. /// /// /// StatusUpdateInterval /// REG_DWORD /// Specifies the interval, in minutes, when the port monitor updates the spooler with the port status. /// /// /// /// To ensure that the spooler redirects jobs to the next available printer in the pool (when the print job is not printed within /// the set time), the port monitor must support SNMP and the network ports in the pool must be configured as "SNMP status enabled." /// The port monitor that supports SNMP is Standard TCP/IP port monitor. /// /// /// In Windows 7 and later versions of Windows, print jobs that are sent to a print server are rendered on the client by default. /// Client-side rendering of print jobs can be configured by setting pKeyName to "PrinterDriverData" and pValueName to the setting /// value in the following table. /// /// /// /// Setting /// Data type /// Description /// /// /// EMFDespoolingSetting /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, enables the default client-side rendering of print jobs. A value /// of 1 disables client-side rendering of print jobs. /// /// /// /// ForceClientSideRendering /// REG_DWORD /// /// A value of 0, or if this value is not present in the registry, will cause the print jobs to be rendered on the client. If a /// print job cannot be rendered on the client, it will be rendered on the server. If a print job cannot be rendered on the server, /// it will fail. A value of 1 will render print jobs on the client. If a print job cannot be rendered on the client, it will fail. /// /// /// /// [PInvokeData("winspool.h", MSDNShortId = "b7faadfc-1c81-4ddf-8fe5-68f4cc0376f1")] public static Win32Error SetPrinterDataEx(HPRINTER hPrinter, string pKeyName, string pValueName, object pData, REG_VALUE_TYPE type = 0) => InlineSetPrinterData(SetPrinterDataEx, hPrinter, pKeyName, pValueName, pData, type); /// The StartDocPrinter function notifies the print spooler that a document is to be spooled for printing. /// /// A handle to the printer. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// The version of the structure to which pDocInfo points. This value must be 1. /// A pointer to a DOC_INFO_1 structure that describes the document to print. /// /// If the function succeeds, the return value identifies the print job. /// If the function fails, the return value is zero. /// /// /// The typical sequence for a print job is as follows: /// /// /// To begin a print job, call StartDocPrinter. /// /// /// To begin each page, call StartPagePrinter. /// /// /// To write data to a page, call WritePrinter. /// /// /// To end each page, call EndPagePrinter. /// /// /// Repeat 2, 3, and 4 for as many pages as necessary. /// /// /// To end the print job, call EndDocPrinter. /// /// /// /// Note that calling StartPagePrinter and EndPagePrinter may not be necessary, such as if the print data type /// includes the page information. /// /// /// When a page in a spooled file exceeds approximately 350 MB, it can fail to print and not send an error message. For example, /// this can occur when printing large EMF files. The page size limit depends on many factors including the amount of virtual memory /// available, the amount of memory allocated by calling processes, and the amount of fragmentation in the process heap. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/startdocprinter DWORD StartDocPrinter( _In_ HANDLE hPrinter, _In_ DWORD // Level, _In_ LPBYTE pDocInfo ); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("winspool.h", MSDNShortId = "caa2bd80-4af3-4968-a5b9-d12f16cac6fc")] public static extern uint StartDocPrinter(HPRINTER hPrinter, uint Level, in DOC_INFO_1 pDocInfo); /// The StartPagePrinter function notifies the spooler that a page is about to be printed on the specified printer. /// /// Handle to a printer. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// The sequence for a print job is as follows: /// /// /// To begin a print job, call StartDocPrinter. /// /// /// To begin each page, call StartPagePrinter. /// /// /// To write data to a page, call WritePrinter. /// /// /// To end each page, call EndPagePrinter. /// /// /// Repeat 2, 3, and 4 for as many pages as necessary. /// /// /// To end the print job, call EndDocPrinter. /// /// /// /// When a page in a spooled file exceeds approximately 350 MB, it can fail to print and not send an error message. For example, /// this can occur when printing large EMF files. The page size limit depends on many factors including the amount of virtual memory /// available, the amount of memory allocated by calling processes, and the amount of fragmentation in the process heap. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/startpageprinter BOOL StartPagePrinter( _In_ HANDLE hPrinter ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "8ac7c47b-b3a7-4642-bfb7-54e014139fbf")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool StartPagePrinter(HPRINTER hPrinter); /// The WritePrinter function notifies the print spooler that data should be written to the specified printer. /// /// A handle to the printer. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// A pointer to an array of bytes that contains the data that should be written to the printer. /// The size, in bytes, of the array. /// A pointer to a value that receives the number of bytes of data that were written to the printer. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// The sequence for a print job is as follows: /// /// /// To begin a print job, call StartDocPrinter. /// /// /// To begin each page, call StartPagePrinter. /// /// /// To write data to a page, call WritePrinter. /// /// /// To end each page, call EndPagePrinter. /// /// /// Repeat 2, 3, and 4 for as many pages as necessary. /// /// /// To end the print job, call EndDocPrinter. /// /// /// /// When a high-level document (such as an Adobe PDF or Microsoft Word file) or other printer data (such PCL, PS, or HPGL) is sent /// directly to a printer, the print settings defined in the document take precedent over Windows print settings. Documents output /// when the value of the pDatatype member of the DOC_INFO_1 structure that was passed in the pDocInfo parameter of the /// StartDocPrinter call is "RAW" must fully describe the DEVMODE-style print job settings in the language understood /// by the hardware. /// /// /// In versions of Windows prior to Windows XP, when a page in a spooled file exceeds approximately 350 MB, it can fail to print and /// not send an error message. For example, this can occur when printing large EMF files. The page size limit in versions of Windows /// prior to Windows XP depends on many factors including the amount of virtual memory available, the amount of memory allocated by /// calling processes, and the amount of fragmentation in the process heap. In Windows XP and later versions of Windows, EMF files /// must be 2GB or less in size. If WritePrinter is used to write non EMF data, such as printer-ready PDL, the size of the /// file is limited only by the available disk space. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/writeprinter BOOL WritePrinter( _In_ HANDLE hPrinter, _In_ LPVOID pBuf, // _In_ DWORD cbBuf, _Out_ LPDWORD pcWritten ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "9411b71f-d686-44ed-9051-d410e5ab228e")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WritePrinter(HPRINTER hPrinter, IntPtr pBuf, uint cbBuf, out uint pcWritten); /// The WritePrinter function notifies the print spooler that data should be written to the specified printer. /// /// A handle to the printer. Use the OpenPrinter or AddPrinter function to retrieve a printer handle. /// /// A pointer to an array of bytes that contains the data that should be written to the printer. /// The size, in bytes, of the array. /// A pointer to a value that receives the number of bytes of data that were written to the printer. /// /// If the function succeeds, the return value is a nonzero value. /// If the function fails, the return value is zero. /// /// /// The sequence for a print job is as follows: /// /// /// To begin a print job, call StartDocPrinter. /// /// /// To begin each page, call StartPagePrinter. /// /// /// To write data to a page, call WritePrinter. /// /// /// To end each page, call EndPagePrinter. /// /// /// Repeat 2, 3, and 4 for as many pages as necessary. /// /// /// To end the print job, call EndDocPrinter. /// /// /// /// When a high-level document (such as an Adobe PDF or Microsoft Word file) or other printer data (such PCL, PS, or HPGL) is sent /// directly to a printer, the print settings defined in the document take precedent over Windows print settings. Documents output /// when the value of the pDatatype member of the DOC_INFO_1 structure that was passed in the pDocInfo parameter of the /// StartDocPrinter call is "RAW" must fully describe the DEVMODE-style print job settings in the language understood /// by the hardware. /// /// /// In versions of Windows prior to Windows XP, when a page in a spooled file exceeds approximately 350 MB, it can fail to print and /// not send an error message. For example, this can occur when printing large EMF files. The page size limit in versions of Windows /// prior to Windows XP depends on many factors including the amount of virtual memory available, the amount of memory allocated by /// calling processes, and the amount of fragmentation in the process heap. In Windows XP and later versions of Windows, EMF files /// must be 2GB or less in size. If WritePrinter is used to write non EMF data, such as printer-ready PDL, the size of the /// file is limited only by the available disk space. /// /// // https://docs.microsoft.com/en-us/windows/win32/printdocs/writeprinter BOOL WritePrinter( _In_ HANDLE hPrinter, _In_ LPVOID pBuf, // _In_ DWORD cbBuf, _Out_ LPDWORD pcWritten ); [DllImport(Lib.Winspool, SetLastError = true, ExactSpelling = true)] [PInvokeData("winspool.h", MSDNShortId = "9411b71f-d686-44ed-9051-d410e5ab228e")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WritePrinter(HPRINTER hPrinter, byte[] pBuf, int cbBuf, out uint pcWritten); [DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool AddPrinterConnection2([Optional] HWND hWnd, string pszName, uint dwLevel, in PRINTER_CONNECTION_INFO_1 pConnectionInfo); private static Win32Error InlineSetPrinterData(Func f, HPRINTER hPrinter, string pKeyName, string pValueName, object pData, REG_VALUE_TYPE type) { var pDataType = pData.GetType(); if (type == 0) type = RegistryTypeExt.GetFromType(pDataType); switch (type) { case REG_VALUE_TYPE.REG_NONE: case REG_VALUE_TYPE.REG_BINARY: using (var str = new NativeMemoryStream()) { str.WriteObject(pData); str.Flush(); return f(hPrinter, pKeyName, pValueName, type, str.Pointer, (uint)str.Length); } case REG_VALUE_TYPE.REG_DWORD: case REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN: var bytes = BitConverter.GetBytes(Convert.ToUInt32(pData)); if (BitConverter.IsLittleEndian && type == REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN || !BitConverter.IsLittleEndian && type == REG_VALUE_TYPE.REG_DWORD) Array.Reverse(bytes); using (var bs = SafeCoTaskMemHandle.CreateFromList(bytes)) return f(hPrinter, pKeyName, pValueName, type, bs, bs.Size); case REG_VALUE_TYPE.REG_MULTI_SZ: using (var ms = SafeCoTaskMemHandle.CreateFromStringList((IEnumerable)pData)) return f(hPrinter, pKeyName, pValueName, type, ms, ms.Size); case REG_VALUE_TYPE.REG_QWORD: var q = Convert.ToUInt64(pData); return f(hPrinter, pKeyName, pValueName, type, new PinnedObject(q), 8); case REG_VALUE_TYPE.REG_SZ: case REG_VALUE_TYPE.REG_EXPAND_SZ: using (var ms = new SafeCoTaskMemString(pData.ToString())) return f(hPrinter, pKeyName, pValueName, type, ms, ms.Size); default: throw new ArgumentException("Cannot convert to a registry format.", nameof(pData)); } } [DllImport(Lib.Winspool, SetLastError = true, EntryPoint = "GetSpoolFileHandle")] private static extern IntPtr InternalGetSpoolFileHandle(HPRINTER hPrinter); private static bool TryGetLevel(string prefix, out uint level) { level = 0; return typeof(T).Name.StartsWith(prefix) && uint.TryParse(typeof(T).Name.Substring(typeof(T).Name.LastIndexOf('_') + 1), out level); } } }