Vanara/PInvoke/Printing/WinSpool.DrvFuncs.cs

1850 lines
104 KiB
C#

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using Vanara.InteropServices;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
namespace Vanara.PInvoke
{
/// <summary>Contains functions, structures and constants from winspool.h.</summary>
public static partial class WinSpool
{
/// <summary>
/// The printer driver and all the files in the printer driver directory must be added. The file time stamps are ignored when
/// dwFlags has a value of IPDFP_COPY_ALL_FILES.
/// </summary>
public const uint IPDFP_COPY_ALL_FILES = 0x00000001;
/// <summary>The options for copying the driver files.</summary>
[PInvokeData("winspool.h", MSDNShortId = "472adb7d-39cc-4c76-b96c-610ff9d276ad")]
[Flags]
public enum APD
{
/// <summary>
/// Add the printer driver only if all the files in the printer-driver directory are newer than any corresponding files
/// currently in use.
/// </summary>
APD_STRICT_UPGRADE = 0x00000001,
/// <summary>
/// Add the printer driver only if all the files in the printer-driver directory are older than any corresponding files
/// currently in use.
/// </summary>
APD_STRICT_DOWNGRADE = 0x00000002,
/// <summary>
/// Add the printer driver and copy all the files in the printer-driver directory. The file time stamps are ignored with this option.
/// </summary>
APD_COPY_ALL_FILES = 0x00000004,
/// <summary>
/// Add the printer driver and copy the files in the printer-driver directory that are newer than any corresponding files that
/// are currently in use. This flag emulates the behavior of AddPrinterDriver.
/// </summary>
APD_COPY_NEW_FILES = 0x00000008,
/// <summary>
/// Add the printer driver using the fully qualified file names specified in the DRIVER_INFO_6 structure. This flag is ORed in
/// conjunction with one of the other copy flags. If this flag is set, AddPrinterDriverEx will fail if the files do not exist
/// where they are specified to exist by the DRIVER_INFO_6 structure. The files do not need to be copied to the system's
/// printer-driver directory. See the Remarks. Windows 2000: This flag is not supported.
/// </summary>
APD_COPY_FROM_DIRECTORY = 0x00000010,
}
/// <summary>The options for deleting files and versions of the driver.</summary>
[PInvokeData("winspool.h", MSDNShortId = "1a3d7c7f-1d45-4877-a8f7-a77f40e3c319")]
[Flags]
public enum DPD
{
/// <summary>Removes any unused driver files.</summary>
DPD_DELETE_UNUSED_FILES = 0x00000001,
/// <summary>
/// Deletes the version specified in dwVersionFlag. This does not ensure that the driver will be removed from the list of
/// supported drivers for the server.
/// </summary>
DPD_DELETE_SPECIFIC_VERSION = 0x00000002,
/// <summary>
/// Deletes the driver only if all its associated files can be removed. The delete operation fails if any of the driver's files
/// are being used by some other installed driver.
/// </summary>
DPD_DELETE_ALL_FILES = 0x00000004,
}
/// <summary>Options for <c>UploadPrinterDriverPackage</c>.</summary>
[PInvokeData("winspool.h", MSDNShortId = "dd3b3a3b-8ded-44ae-85dd-e630bc62e898")]
[Flags]
public enum UPDP
{
/// <summary>The UI will not be shown during the upload.</summary>
UPDP_SILENT_UPLOAD = 0x00000001,
/// <summary>The files will be uploaded even if the package is already in the server's driver store.</summary>
UPDP_UPLOAD_ALWAYS = 0x00000002,
/// <summary>
/// The server's driver store will be checked before upload to see if the package is already there. This setting is ignored if
/// UPDP_UPLOAD_ALWAYS is set.
/// </summary>
UPDP_CHECK_DRIVERSTORE = 0x00000004,
}
/// <summary>The <c>AddMonitor</c> function installs a local port monitor and links the configuration, data, and monitor files.</summary>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the monitor should be installed. For
/// systems that support only local installation of monitors, this string should be <c>NULL</c>.
/// </param>
/// <param name="Level">The version of the structure to which pMonitors points. This value must be 2.</param>
/// <param name="pMonitors">
/// <para>
/// A pointer to a <c>MONITOR_INFO_2</c> structure. If the <c>pEnvironment</c> member of the pMonitors structure is <c>NULL</c>, the
/// current environment of the caller (client), not of the destination (server), is used.
/// </para>
/// <para>
/// Note that the call will fail if the environment does not match the environment of the server, that is, you can only add a
/// monitor that was written for the architecture of the server.
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>The caller must have the SeLoadDriverPrivilege.</para>
/// <para>
/// Before an application calls the <c>AddMonitor</c> function, all files required by the monitor must be copied to the SYSTEM32 directory.
/// </para>
/// <para>To determine the port monitors that are currently installed, call the <c>EnumMonitors</c> function.</para>
/// <para>To remove a monitor added by <c>AddMonitor</c>, call the <c>DeleteMonitor</c> function.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/addmonitor BOOL AddMonitor( _In_ LPTSTR pName, _In_ DWORD Level, _In_
// LPBYTE pMonitors );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "6a556422-5360-42d2-b177-dba0498c06d8")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AddMonitor([Optional] string pName, uint Level, [In] IntPtr pMonitors);
/// <summary>The <c>AddMonitor</c> function installs a local port monitor and links the configuration, data, and monitor files.</summary>
/// <typeparam name="T">The type of the structure to which pMonitors points. This value must be <c>MONITOR_INFO_2</c>.</typeparam>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the monitor should be installed. For
/// systems that support only local installation of monitors, this string should be <c>NULL</c>.
/// </param>
/// <param name="pMonitors">
/// <para>
/// A <c>MONITOR_INFO_2</c> structure. If the <c>pEnvironment</c> member of the pMonitors structure is <c>NULL</c>, the current
/// environment of the caller (client), not of the destination (server), is used.
/// </para>
/// <para>
/// Note that the call will fail if the environment does not match the environment of the server, that is, you can only add a
/// monitor that was written for the architecture of the server.
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>The caller must have the SeLoadDriverPrivilege.</para>
/// <para>
/// Before an application calls the <c>AddMonitor</c> function, all files required by the monitor must be copied to the SYSTEM32 directory.
/// </para>
/// <para>To determine the port monitors that are currently installed, call the <c>EnumMonitors</c> function.</para>
/// <para>To remove a monitor added by <c>AddMonitor</c>, call the <c>DeleteMonitor</c> function.</para>
/// </remarks>
[PInvokeData("winspool.h", MSDNShortId = "6a556422-5360-42d2-b177-dba0498c06d8")]
public static bool AddMonitor<T>([Optional] string pName, in T pMonitors) where T : struct
{
if (!TryGetLevel<T>("MONITOR_INFO_", out var lvl))
throw new ArgumentException($"{nameof(AddMonitor)} cannot process a structure of type {typeof(T).Name}.");
using var mem = SafeCoTaskMemHandle.CreateFromStructure(pMonitors);
return AddMonitor(pName, lvl, mem);
}
/// <summary>
/// The <c>AddPort</c> function adds the name of a port to the list of supported ports. The <c>AddPort</c> function is exported by
/// the port monitor.
/// </summary>
/// <param name="pName">
/// A pointer to a zero-terminated string that specifies the name of the server to which the port is connected. If this parameter is
/// <c>NULL</c>, the port is local.
/// </param>
/// <param name="hWnd">A handle to the parent window of the <c>AddPort</c> dialog box.</param>
/// <param name="pMonitorName">A pointer to a zero-terminated string that specifies the monitor associated with the port.</param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>
/// The <c>AddPort</c> function browses the network to find existing ports, and displays a dialog box for the user. The
/// <c>AddPort</c> function should validate the port name entered by the user by calling <c>EnumPorts</c> to ensure that no
/// duplicate names exist.
/// </para>
/// <para>
/// The caller of the <c>AddPort</c> function must have SERVER_ACCESS_ADMINISTER access to the server to which the port is connected.
/// </para>
/// <para>
/// To add a port without displaying a dialog box, call the <c>XcvData</c> function instead of <c>AddPort</c>. For more information
/// about <c>XcvData</c>, see the Microsoft Windows Driver Development Kit (DDK).
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/addport BOOL AddPort( _In_ LPTSTR pName, _In_ HWND hWnd, _In_ LPTSTR
// pMonitorName );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "9191d507-9167-4488-a4b4-286590a8a62a")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AddPort([Optional] string pName, HWND hWnd, string pMonitorName);
/// <summary>
/// <para>
/// The <c>AddPrinterDriver</c> function installs a local or remote printer driver and associates the configuration, data, and
/// driver files.
/// </para>
/// <para>
/// For more flexibility in installing or upgrading printer drivers, use the <c>AddPrinterDriverEx</c> function because it allows
/// strict upgrade, strict downgrade, copying of newer files only, and copying of all files (regardless of the file time stamps).
/// </para>
/// </summary>
/// <param name="pName">
/// <para>A pointer to a null-terminated string that specifies the name of the server on which the driver should be installed.</para>
/// <para>If pName is <c>NULL</c>, the driver will be installed locally.</para>
/// </param>
/// <param name="Level">
/// <para>The version of the structure to which pDriverInfo points.</para>
/// <para>This value can be 2, 3, 4, 6, or 8.</para>
/// </param>
/// <param name="pDriverInfo">
/// <para>A pointer to a structure containing printer driver information. This depends on the value of Level.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Printer Drive Structure</term>
/// </listheader>
/// <item>
/// <term>2</term>
/// <term>DRIVER_INFO_2</term>
/// </item>
/// <item>
/// <term>3</term>
/// <term>DRIVER_INFO_3</term>
/// </item>
/// <item>
/// <term>4</term>
/// <term>DRIVER_INFO_4</term>
/// </item>
/// <item>
/// <term>6</term>
/// <term>DRIVER_INFO_6</term>
/// </item>
/// <item>
/// <term>8</term>
/// <term>DRIVER_INFO_8</term>
/// </item>
/// </list>
/// <para>
/// If the <c>pEnvironment</c> member of the structure pointed to by pDriverInfo is <c>NULL</c>, the current environment of the
/// caller/client (not of the destination/server) is used.
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>The caller must have the SeLoadDriverPrivilege.</para>
/// <para>
/// Before an application calls the <c>AddPrinterDriver</c> function, all files required by the driver must be copied to the
/// system's printer-driver directory. An application can retrieve the name of this directory by calling the
/// <c>GetPrinterDriverDirectory</c> function.
/// </para>
/// <para>An application can determine which printer drivers are currently installed by calling the <c>EnumPrinterDrivers</c> function.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/addprinterdriver BOOL AddPrinterDriver( _In_ LPTSTR pName, _In_ DWORD
// Level, _In_ LPBYTE pDriverInfo );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "0f762800-f5a5-40ea-8be1-7fd8bda23788")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AddPrinterDriver([Optional] string pName, uint Level, [In] IntPtr pDriverInfo);
/// <summary>
/// The <c>AddPrinterDriverEx</c> function installs a local or remote printer driver and links the configuration, data, and driver
/// files. Besides having the capabilities of <c>AddPrinterDriver</c>, it also has options that permit strict upgrade, strict
/// downgrade, copying of newer files only, and copying of all files (regardless of file time stamps).
/// </summary>
/// <typeparam name="T">The type of the structure containing printer driver information.</typeparam>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the driver should be installed. If this
/// parameter is <c>NULL</c>, the function installs the driver on the local computer.
/// </param>
/// <param name="pDriverInfo">
/// <para>A structure containing printer driver information. It can be one of the following.</para>
/// <list type="table">
/// <listheader>
/// <term>Value of Level</term>
/// <term>DRIVER_INFO_* Structure</term>
/// </listheader>
/// <item>
/// <term>2</term>
/// <term>DRIVER_INFO_2</term>
/// </item>
/// <item>
/// <term>3</term>
/// <term>DRIVER_INFO_3</term>
/// </item>
/// <item>
/// <term>4</term>
/// <term>DRIVER_INFO_4</term>
/// </item>
/// <item>
/// <term>6</term>
/// <term>DRIVER_INFO_6</term>
/// </item>
/// <item>
/// <term>8</term>
/// <term>DRIVER_INFO_8</term>
/// </item>
/// </list>
/// <para>
/// If the <c>pEnvironment</c> member of the structure pointed to by pDriverInfo is <c>NULL</c>, the function uses the current
/// environment of the caller/client, not the environment of the destination/server.
/// </para>
/// </param>
/// <param name="dwFileCopyFlags">
/// <para>The options for copying the driver files. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>APD_COPY_ALL_FILES</term>
/// <term>
/// Add the printer driver and copy all the files in the printer-driver directory. The file time stamps are ignored with this option.
/// </term>
/// </item>
/// <item>
/// <term>APD_COPY_FROM_DIRECTORY</term>
/// <term>
/// Add the printer driver using the fully qualified file names specified in the DRIVER_INFO_6 structure. This flag is ORed in
/// conjunction with one of the other copy flags. If this flag is set, AddPrinterDriverEx will fail if the files do not exist where
/// they are specified to exist by the DRIVER_INFO_6 structure. The files do not need to be copied to the system's printer-driver
/// directory. See the Remarks. Windows 2000: This flag is not supported.
/// </term>
/// </item>
/// <item>
/// <term>APD_COPY_NEW_FILES</term>
/// <term>
/// Add the printer driver and copy the files in the printer-driver directory that are newer than any corresponding files that are
/// currently in use. This flag emulates the behavior of AddPrinterDriver.
/// </term>
/// </item>
/// <item>
/// <term>APD_STRICT_DOWNGRADE</term>
/// <term>
/// Add the printer driver only if all the files in the printer-driver directory are older than any corresponding files currently in use.
/// </term>
/// </item>
/// <item>
/// <term>APD_STRICT_UPGRADE</term>
/// <term>
/// Add the printer driver only if all the files in the printer-driver directory are newer than any corresponding files currently in use.
/// </term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// <para>
/// If the printer driver is known to have problems working with the operating system, <c>AddPrinterDriverEx</c> will fail with one
/// of the following error codes:
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Error Code</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_PRINTER_DRIVER_BLOCKED</term>
/// <term>The driver does not work on the operating system.</term>
/// </item>
/// <item>
/// <term>ERROR_PRINTER_DRIVER_WARNED</term>
/// <term>
/// The driver is unreliable on the operating system. However, if APD_INSTALL_WARNED_DRIVER is specified, the driver is installed
/// and no warning is given.
/// </term>
/// </item>
/// </list>
/// <para>For more information, see the Remarks.</para>
/// </returns>
/// <remarks>
/// <para>The caller must have the SeLoadDriverPrivilege.</para>
/// <para>
/// Before calling the <c>AddPrinterDriverEx</c> function, all files required by the driver must be copied to the system's
/// printer-driver directory. To retrieve the name of this directory, call the <c>GetPrinterDriverDirectory</c> function.
/// </para>
/// <para>To determine which printer drivers are currently installed, call the <c>EnumPrinterDrivers</c> function.</para>
/// <para>
/// If the printer driver has been successfully added, the function calls the DrvDriverEvent (DRIVER_EVENT_INITIALIZE, Level,
/// DRIVER_INFO_*, lparam ) function to allow the driver to perform any initializations required during the installation of a
/// printer driver. For more information about <c>DrvDriverEvent</c>, see the Microsoft Windows Driver Development Kit (DDK)
/// </para>
/// <para>
/// The driver should not use a UI call during the call to <c>DrvDriverEvent</c>. 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 DDK.
/// </para>
/// <para>
/// The files that are referenced in the <c>DRIVER_INFO_6</c> structure must be local to the machine from which the call is made. A
/// file name can be a UNC name as long as the UNC name is the local machine.
/// </para>
/// </remarks>
[PInvokeData("winspool.h", MSDNShortId = "472adb7d-39cc-4c76-b96c-610ff9d276ad")]
public static bool AddPrinterDriverEx<T>([Optional] string pName, in T pDriverInfo, APD dwFileCopyFlags = APD.APD_COPY_NEW_FILES) where T : struct
{
if (!TryGetLevel<T>("DRIVER_INFO_", out var lvl))
throw new ArgumentException($"{nameof(AddPrinterDriverEx)} cannot process a structure of type {typeof(T).Name}.");
using var mem = SafeCoTaskMemHandle.CreateFromStructure(pDriverInfo);
return AddPrinterDriverEx(pName, lvl, mem, dwFileCopyFlags);
}
/// <summary>
/// The <c>AddPrinterDriverEx</c> function installs a local or remote printer driver and links the configuration, data, and driver
/// files. Besides having the capabilities of <c>AddPrinterDriver</c>, it also has options that permit strict upgrade, strict
/// downgrade, copying of newer files only, and copying of all files (regardless of file time stamps).
/// </summary>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the driver should be installed. If this
/// parameter is <c>NULL</c>, the function installs the driver on the local computer.
/// </param>
/// <param name="Level">The version of the structure to which pDriverInfo points. This value can be 2, 3, 4, 6, or 8.</param>
/// <param name="pDriverInfo">
/// <para>A pointer to a structure containing printer driver information. It can be one of the following.</para>
/// <list type="table">
/// <listheader>
/// <term>Value of Level</term>
/// <term>DRIVER_INFO_* Structure</term>
/// </listheader>
/// <item>
/// <term>2</term>
/// <term>DRIVER_INFO_2</term>
/// </item>
/// <item>
/// <term>3</term>
/// <term>DRIVER_INFO_3</term>
/// </item>
/// <item>
/// <term>4</term>
/// <term>DRIVER_INFO_4</term>
/// </item>
/// <item>
/// <term>6</term>
/// <term>DRIVER_INFO_6</term>
/// </item>
/// <item>
/// <term>8</term>
/// <term>DRIVER_INFO_8</term>
/// </item>
/// </list>
/// <para>
/// If the <c>pEnvironment</c> member of the structure pointed to by pDriverInfo is <c>NULL</c>, the function uses the current
/// environment of the caller/client, not the environment of the destination/server.
/// </para>
/// </param>
/// <param name="dwFileCopyFlags">
/// <para>The options for copying the driver files. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>APD_COPY_ALL_FILES</term>
/// <term>
/// Add the printer driver and copy all the files in the printer-driver directory. The file time stamps are ignored with this option.
/// </term>
/// </item>
/// <item>
/// <term>APD_COPY_FROM_DIRECTORY</term>
/// <term>
/// Add the printer driver using the fully qualified file names specified in the DRIVER_INFO_6 structure. This flag is ORed in
/// conjunction with one of the other copy flags. If this flag is set, AddPrinterDriverEx will fail if the files do not exist where
/// they are specified to exist by the DRIVER_INFO_6 structure. The files do not need to be copied to the system's printer-driver
/// directory. See the Remarks. Windows 2000: This flag is not supported.
/// </term>
/// </item>
/// <item>
/// <term>APD_COPY_NEW_FILES</term>
/// <term>
/// Add the printer driver and copy the files in the printer-driver directory that are newer than any corresponding files that are
/// currently in use. This flag emulates the behavior of AddPrinterDriver.
/// </term>
/// </item>
/// <item>
/// <term>APD_STRICT_DOWNGRADE</term>
/// <term>
/// Add the printer driver only if all the files in the printer-driver directory are older than any corresponding files currently in use.
/// </term>
/// </item>
/// <item>
/// <term>APD_STRICT_UPGRADE</term>
/// <term>
/// Add the printer driver only if all the files in the printer-driver directory are newer than any corresponding files currently in use.
/// </term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// <para>
/// If the printer driver is known to have problems working with the operating system, <c>AddPrinterDriverEx</c> will fail with one
/// of the following error codes:
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Error Code</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ERROR_PRINTER_DRIVER_BLOCKED</term>
/// <term>The driver does not work on the operating system.</term>
/// </item>
/// <item>
/// <term>ERROR_PRINTER_DRIVER_WARNED</term>
/// <term>
/// The driver is unreliable on the operating system. However, if APD_INSTALL_WARNED_DRIVER is specified, the driver is installed
/// and no warning is given.
/// </term>
/// </item>
/// </list>
/// <para>For more information, see the Remarks.</para>
/// </returns>
/// <remarks>
/// <para>The caller must have the SeLoadDriverPrivilege.</para>
/// <para>
/// Before calling the <c>AddPrinterDriverEx</c> function, all files required by the driver must be copied to the system's
/// printer-driver directory. To retrieve the name of this directory, call the <c>GetPrinterDriverDirectory</c> function.
/// </para>
/// <para>To determine which printer drivers are currently installed, call the <c>EnumPrinterDrivers</c> function.</para>
/// <para>
/// If the printer driver has been successfully added, the function calls the DrvDriverEvent (DRIVER_EVENT_INITIALIZE, Level,
/// DRIVER_INFO_*, lparam ) function to allow the driver to perform any initializations required during the installation of a
/// printer driver. For more information about <c>DrvDriverEvent</c>, see the Microsoft Windows Driver Development Kit (DDK)
/// </para>
/// <para>
/// The driver should not use a UI call during the call to <c>DrvDriverEvent</c>. 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 DDK.
/// </para>
/// <para>
/// The files that are referenced in the <c>DRIVER_INFO_6</c> structure must be local to the machine from which the call is made. A
/// file name can be a UNC name as long as the UNC name is the local machine.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/addprinterdriverex BOOL AddPrinterDriverEx( _In_ LPTSTR pName, _In_
// DWORD Level, _Inout_ LPBYTE pDriverInfo, _In_ DWORD dwFileCopyFlags );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "472adb7d-39cc-4c76-b96c-610ff9d276ad")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AddPrinterDriverEx([Optional] string pName, uint Level, [In, Out] IntPtr pDriverInfo, APD dwFileCopyFlags);
/// <summary>
/// The <c>AddPrintProcessor</c> function installs a print processor on the specified server and adds the print-processor name to
/// the list of supported print processors.
/// </summary>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the print processor should be installed. If
/// this parameter is <c>NULL</c>, the print processor is installed locally.
/// </param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment (for example, Windows x86, Windows IA64, or Windows x64).
/// If this parameter is <c>NULL</c>, the current environment of the caller/client (not of the destination/server) is used.
/// </param>
/// <param name="pPathName">
/// A pointer to a null-terminated string that specifies the name of the file that contains the print processor. This file must be
/// in the system print-processor directory.
/// </param>
/// <param name="pPrintProcessorName">A pointer to a null-terminated string that specifies the name of the print processor.</param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>The caller must have the SeLoadDriverPrivilege.</para>
/// <para>
/// Before calling the <c>AddPrintProcessor</c> function, an application should verify that the file containing the print processor
/// is stored in the system print-processor directory. An application can retrieve the name of the system print-processor directory
/// by calling the <c>GetPrintProcessorDirectory</c> function.
/// </para>
/// <para>An application can determine the name of existing print processors by calling the <c>EnumPrintProcessors</c> function.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/addprintprocessor BOOL AddPrintProcessor( _In_ LPTSTR pName, _In_ LPTSTR
// pEnvironment, _In_ LPTSTR pPathName, _In_ LPTSTR pPrintProcessorName );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "99899cee-f74d-4405-8ea5-616e3769aba9")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AddPrintProcessor([Optional] string pName, [Optional] string pEnvironment, string pPathName, string pPrintProcessorName);
/// <summary>
/// The <c>AddPrintProvidor</c> function installs a local print provider and links the configuration, data, and provider files.
/// </summary>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the provider should be installed. For
/// systems that only support local installation of providers, this parameter should be <c>NULL</c>.
/// </param>
/// <param name="Level">
/// <para>The level of the structure to which pProviderInfo points. It can be one of the following.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>1</term>
/// <term>Function uses a PROVIDOR_INFO_1 structure.</term>
/// </item>
/// <item>
/// <term>2</term>
/// <term>Function uses a PROVIDOR_INFO_2 structure.</term>
/// </item>
/// </list>
/// </param>
/// <param name="pProviderInfo">A pointer to a print provider structure, as indicated by Level.</param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>
/// Before an application calls the <c>AddPrintProvidor</c> function, all files required by the provider must be copied to the
/// SYSTEM32 directory.
/// </para>
/// <para>A provider added by <c>AddPrintProvidor</c> may be removed by calling <c>DeletePrintProvidor</c>.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/addprintprovidor BOOL AddPrintProvidor( _In_ LPTSTR pName, _In_ DWORD
// Level, _In_ LPBYTE pProviderInfo );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "f34549c3-0474-48ba-9307-5b36f02dbe1c")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AddPrintProvidor([Optional] string pName, uint Level, [In] IntPtr pProviderInfo);
/// <summary>
/// The <c>AddPrintProvidor</c> function installs a local print provider and links the configuration, data, and provider files.
/// </summary>
/// <typeparam name="T">The type of the structure containing print provider information.</typeparam>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the provider should be installed. For
/// systems that only support local installation of providers, this parameter should be <c>NULL</c>.
/// </param>
/// <param name="pProviderInfo">
/// <para>A print provider structure. It can be one of the following.</para>
/// <list type="bullet">
/// <item>
/// <term>Function uses a PROVIDOR_INFO_1 structure.</term>
/// </item>
/// <item>
/// <term>Function uses a PROVIDOR_INFO_2 structure.</term>
/// </item>
/// </list>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <exception cref="System.ArgumentException"></exception>
/// <remarks>
/// <para>
/// Before an application calls the <c>AddPrintProvidor</c> function, all files required by the provider must be copied to the
/// SYSTEM32 directory.
/// </para>
/// <para>A provider added by <c>AddPrintProvidor</c> may be removed by calling <c>DeletePrintProvidor</c>.</para>
/// </remarks>
[PInvokeData("winspool.h", MSDNShortId = "f34549c3-0474-48ba-9307-5b36f02dbe1c")]
public static bool AddPrintProvidor<T>([Optional] string pName, in T pProviderInfo) where T : struct
{
if (!TryGetLevel<T>("PROVIDOR_INFO_", out var lvl))
throw new ArgumentException($"{nameof(AddPrintProvidor)} cannot process a structure of type {typeof(T).Name}.");
using var mem = SafeCoTaskMemHandle.CreateFromStructure(pProviderInfo);
return AddPrintProvidor(pName, lvl, mem);
}
/// <summary>
/// The <c>CorePrinterDriverInstalled</c> function reports whether a core printer driver with a specified GUID, date, and version is installed.
/// </summary>
/// <param name="pszServer">
/// Pointer to a constant, null-terminated string that specifies the name of the print server. Use <c>NULL</c> for the local computer.
/// </param>
/// <param name="pszEnvironment">
/// Pointer to a constant, null-terminated string that specifies the processor architecture (for example, Windows NT x86). This can
/// be <c>NULL</c>.
/// </param>
/// <param name="CoreDriverGUID">The GUID of the core printer driver.</param>
/// <param name="ftDriverDate">The date of the core printer driver.</param>
/// <param name="dwlDriverVersion">The version of the core printer driver.</param>
/// <param name="pbDriverInstalled">A pointer to <c>TRUE</c> if the driver, or a newer version, is installed, <c>FALSE</c> otherwise.</param>
/// <returns>
/// <para>If the operation succeeds, the return value is S_OK, otherwise the <c>HRESULT</c> will contain an error code.</para>
/// <para>For more information about COM error codes, see Error Handling.</para>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/coreprinterdriverinstalled HRESULT CorePrinterDriverInstalled( _In_
// LPCTSTR pszServer, _In_ LPCTSTR pszEnvironment, _In_ GUID CoreDriverGUID, _In_ FILETIME ftDriverDate, _In_ DWORDLONG
// dwlDriverVersion, _Out_ BOOL *pbDriverInstalled );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "fb859aca-bb7b-495d-bd38-16ffa084c240")]
public static extern HRESULT CorePrinterDriverInstalled([Optional] string pszServer, [Optional] string pszEnvironment, Guid CoreDriverGUID, FILETIME ftDriverDate, ulong dwlDriverVersion, [MarshalAs(UnmanagedType.Bool)] out bool pbDriverInstalled);
/// <summary>The <c>DeleteMonitor</c> function removes a port monitor added by the <c>AddMonitor</c> function.</summary>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server from which the monitor is to be removed. If this
/// parameter is <c>NULL</c>, the port monitor is removed locally.
/// </param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment from which the monitor is to be removed (for example,
/// Windows x86, Windows IA64, or Windows x64). If this parameter is <c>NULL</c>, the monitor is removed from the current
/// environment of the calling application and client machine (not of the destination application and print server).
/// </param>
/// <param name="pMonitorName">A pointer to a null-terminated string that specifies the name of the monitor to be removed.</param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>The caller must have SeLoadDriverPrivilege.</remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/deletemonitor BOOL DeleteMonitor( _In_ LPTSTR pName, _In_ LPTSTR
// pEnvironment, _In_ LPTSTR pMonitorName );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "32548d4f-830a-471d-8a72-c0f62f43ffa2")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteMonitor([Optional] string pName, [Optional] string pEnvironment, string pMonitorName);
/// <summary>The <c>DeletePort</c> function displays a dialog box that allows the user to delete a port name.</summary>
/// <param name="pName">
/// A pointer to a zero-terminated string that specifies the name of the server for which the port should be deleted. If this
/// parameter is <c>NULL</c>, a local port is deleted.
/// </param>
/// <param name="hWnd">A handle to the parent window of the port-deletion dialog box.</param>
/// <param name="pPortName">A pointer to a zero-terminated string that specifies the name of the port that should be deleted.</param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>An application can retrieve the names of valid ports by calling the <c>EnumPorts</c> function.</para>
/// <para>The <c>DeletePort</c> function returns an error if a printer is currently connected to the specified port.</para>
/// <para>
/// The caller of the <c>DeletePort</c> function must have SERVER_ACCESS_ADMINISTER access to the server to which the port is connected.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/deleteport BOOL DeletePort( _In_ LPTSTR pName, _In_ HWND hWnd, _In_
// LPTSTR pPortName );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "5f5788c2-c781-4106-abd2-98556d0a22de")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeletePort([Optional] string pName, HWND hWnd, string pPortName);
/// <summary>
/// <para>
/// The <c>DeletePrinterDriver</c> function removes the specified printer-driver name from the list of names of supported drivers on
/// a server.
/// </para>
/// <para>
/// To delete the files associated with the driver in addition to removing the specified printer-driver name from the list of names
/// of supported drivers for a server, use the <c>DeletePrinterDriverEx</c> function.
/// </para>
/// <para>
/// <c>DeletePrinterDriver</c> deletes a driver only if no version of the driver is in use for the specified environment.
/// <c>DeletePrinterDriverEx</c> can delete specific versions of the driver.
/// </para>
/// </summary>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server from which the driver is to be deleted. If this
/// parameter is <c>NULL</c>, the printer-driver name will be removed locally.
/// </param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment from which the driver is to be deleted (for example,
/// Windows x86, Windows IA64, or Windows x64). If this parameter is <c>NULL</c>, the driver name is deleted from the current
/// environment of the calling application and client machine (not of the destination application and print server).
/// </param>
/// <param name="pDriverName">A pointer to a null-terminated string specifying the name of the driver that should be deleted.</param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>The caller must have the SeLoadDriverPrivilege.</para>
/// <para>
/// The <c>DeletePrinterDriver</c> function does not delete the associated files, it merely removes the driver name from the list
/// returned by the <c>EnumPrinterDrivers</c> function.
/// </para>
/// <para>Before calling <c>DeletePrinterDriver</c>, you must delete all printer objects that use the printer driver.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/deleteprinterdriver BOOL DeletePrinterDriver( _In_ LPTSTR pName, _In_
// LPTSTR pEnvironment, _In_ LPTSTR pDriverName );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "b159bd8b-3416-44a5-91bf-c0447ed6b465")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeletePrinterDriver([Optional] string pName, [Optional] string pEnvironment, string pDriverName);
/// <summary>
/// The <c>DeletePrinterDriverEx</c> function removes the specified printer-driver name from the list of names of supported drivers
/// on a server and deletes the files associated with the driver. This function can also delete specific versions of the driver.
/// </summary>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server from which the driver is to be deleted. If this
/// parameter is <c>NULL</c>, the function deletes the printer-driver from the local computer.
/// </param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment from which the driver is to be deleted (for example,
/// Windows NT x86, Windows IA64, or Windows x64). If this parameter is <c>NULL</c>, the driver name is deleted from the current
/// environment of the calling application and client computer (not of the destination application and print server).
/// </param>
/// <param name="pDriverName">A pointer to a null-terminated string specifying the name of the driver to delete.</param>
/// <param name="dwDeleteFlag">
/// <para>The options for deleting files and versions of the driver. This parameter can be one or more of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>DPD_DELETE_SPECIFIC_VERSION</term>
/// <term>
/// Deletes the version specified in dwVersionFlag. This does not ensure that the driver will be removed from the list of supported
/// drivers for the server.
/// </term>
/// </item>
/// <item>
/// <term>DPD_DELETE_UNUSED_FILES</term>
/// <term>Removes any unused driver files.</term>
/// </item>
/// <item>
/// <term>DPD_DELETE_ALL_FILES</term>
/// <term>
/// Deletes the driver only if all its associated files can be removed. The delete operation fails if any of the driver's files are
/// being used by some other installed driver.
/// </term>
/// </item>
/// </list>
/// <para>
/// If DPD_DELETE_SPECIFIC_VERSION is not specified, the function deletes all versions of the driver if none of them is in use. If
/// neither DPD_DELETE_UNUSED_FILES nor DPD_DELETE_ALL_FILES is specified, the function does not delete driver files.
/// </para>
/// </param>
/// <param name="dwVersionFlag">
/// The version of the driver to be deleted. This parameter can be 0, 1, 2 or 3. This parameter is used only if dwDeleteFlag
/// includes the DPD_DELETE_SPECIFIC_VERSION flag.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>
/// Before the function deletes the driver files, it calls the driver's <c>DrvDriverEvent</c> function, allowing the driver to
/// remove any private files that are not used. For more information about <c>DrvDriverEvent</c>, see the Microsoft Windows Driver
/// Development Kit (DDK).
/// </para>
/// <para>If the driver files are currently loaded, the function moves them to a temp directory and marks them for deletion on restart.</para>
/// <para>Before calling <c>DeletePrinterDriverEx</c>, you must delete all printer objects that use the printer driver.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/deleteprinterdriverex BOOL DeletePrinterDriverEx( _In_ LPTSTR pName,
// _In_ LPTSTR pEnvironment, _In_ LPTSTR pDriverName, _In_ DWORD dwDeleteFlag, _In_ DWORD dwVersionFlag );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "1a3d7c7f-1d45-4877-a8f7-a77f40e3c319")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeletePrinterDriverEx([Optional] string pName, [Optional] string pEnvironment, string pDriverName, DPD dwDeleteFlag, uint dwVersionFlag = 0);
/// <summary>Deletes a printer driver package from the driver store.</summary>
/// <param name="pszServer">
/// A pointer to a constant, null-terminated string that specifies the name of the print server from which the driver package is
/// being deleted. A <c>NULL</c> pointer value means the local computer.
/// </param>
/// <param name="pszInfPath">A pointer to a constant, null-terminated string that specifies the path to the driver's *.inf file.</param>
/// <param name="pszEnvironment">
/// A pointer to a constant, null-terminated string that specifies the processor architecture (for example, Windows NT x86). This
/// can be <c>NULL</c>.
/// </param>
/// <returns>
/// <para>S_OK, if the operation succeeds.</para>
/// <para>E_ACCESSDENIED, if the package was shipped with Windows.</para>
/// <para>HRESULT_CODE(ERROR_PRINT_DRIVER_PACKAGE_IN_USE), if the package is being used.</para>
/// <para>Otherwise the <c>HRESULT</c> will contain an error code.</para>
/// <para>For more information about COM error codes, see Error Handling.</para>
/// </returns>
/// <remarks>
/// <para>The driver store is typically %windir%\inf or %windir%\System32\DriverStore\FileRepository.</para>
/// <para>A driver package that shipped with Windows cannot be removed with this function.</para>
/// <para>The user must have printer administration privileges.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/deleteprinterdriverpackage HRESULT DeletePrinterDriverPackage( _In_
// LPCTSTR pszServer, _In_ LPCTSTR pszInfPath, _In_ LPCTSTR pszEnvironment );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "a43a94d1-097e-457c-bce9-d4c434ecfa93")]
public static extern HRESULT DeletePrinterDriverPackage([Optional] string pszServer, string pszInfPath, [Optional] string pszEnvironment);
/// <summary>The <c>DeletePrintProcessor</c> function removes a print processor added by the <c>AddPrintProcessor</c> function.</summary>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server from which the processor is to be removed. If this
/// parameter is <c>NULL</c>, the printer processor is removed locally.
/// </param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment from which the processor is to be removed (for example,
/// Windows NT x86, Windows IA64, or Windows x64). If this parameter is <c>NULL</c>, the processor is removed from the current
/// environment of the calling application and client machine (not of the destination application and print server). <c>NULL</c> is
/// the recommended value, as it provides maximum portability.
/// </param>
/// <param name="pPrintProcessorName">A pointer to a null-terminated string that specifies the name of the processor to be removed.</param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>The caller must have the SeLoadDriverPrivilege.</remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/deleteprintprocessor BOOL DeletePrintProcessor( _In_ LPTSTR pName, _In_
// LPTSTR pEnvironment, _In_ LPTSTR pPrintProcessorName );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "65c77874-aa2c-4b4c-b218-fad361270a3e")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeletePrintProcessor([Optional] string pName, [Optional] string pEnvironment, string pPrintProcessorName);
/// <summary>The <c>DeletePrintProvidor</c> function removes a print provider added by the <c>AddPrintProvidor</c> function.</summary>
/// <param name="pName">Reserved; must be <c>NULL</c>.</param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment from which the provider is to be removed (for example,
/// Windows NT x86, Windows IA64, or Windows x64). If this parameter is <c>NULL</c>, the provider is removed from the current
/// environment of the calling application and client machine (not of the destination application and print server). <c>NULL</c> is
/// the recommended value because it provides maximum portability.
/// </param>
/// <param name="pPrintProviderName">A pointer to a null-terminated string that specifies the name of the provider to be removed.</param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/deleteprintprovidor BOOL DeletePrintProvidor( _In_ LPTSTR pName, _In_
// LPTSTR pEnvironment, _In_ LPTSTR pPrintProviderName );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "b7104f9a-111c-4904-a355-063bb4cc81f1")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeletePrintProvidor([Optional] string pName, [Optional] string pEnvironment, string pPrintProviderName);
/// <summary>Retrieves GUID, version, and date of all core printer drivers and the path to their packages.</summary>
/// <param name="pszServer">
/// A pointer to a constant, null-terminated string that specifies the name of the print server. Use <c>NULL</c> for the local computer.
/// </param>
/// <param name="pszEnvironment">
/// A pointer to a constant, null-terminated string that specifies the processor architecture (for example, Windows NT x86). This
/// can be <c>NULL</c>.
/// </param>
/// <returns>A sequence of <c>CORE_PRINTER_DRIVER</c> structures.</returns>
/// <remarks>
/// 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.
/// </remarks>
public static IEnumerable<CORE_PRINTER_DRIVER> EnumCorePrinterDrivers([Optional] string pszServer, [Optional] string pszEnvironment)
{
const string subKey32 = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\PackageInstallation\Windows NT x86\CorePrinterDrivers";
const string subKey64 = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\PackageInstallation\Windows x64\CorePrinterDrivers";
var is64bit = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432"));
using var baseKey = string.IsNullOrEmpty(pszServer) ? null : RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, pszServer);
using var reg = (baseKey ?? Registry.LocalMachine).OpenSubKey(is64bit ? subKey64 : subKey32, false);// RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.EnumerateSubKeys);
var keys = reg?.GetSubKeyNames();
if (keys?.Length == 0) return new CORE_PRINTER_DRIVER[0];
var drvs = new CORE_PRINTER_DRIVER[keys.Length];
GetCorePrinterDrivers(pszServer, pszEnvironment, keys, (uint)keys.Length, drvs).ThrowIfFailed();
return drvs;
}
/// <summary>The <c>EnumMonitors</c> function retrieves information about the port monitors installed on the specified server.</summary>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the monitors reside. If this parameter is
/// <c>NULL</c>, the local monitors are enumerated.
/// </param>
/// <param name="Level">
/// <para>The version of the structure pointed to by pMonitors.</para>
/// <para>This value can be 1 or 2.</para>
/// </param>
/// <param name="pMonitors">
/// <para>
/// A pointer to a buffer that receives an array of structures. The buffer must be large enough to store the strings referenced by
/// the structure members.
/// </para>
/// <para>
/// To determine the required buffer size, call <c>EnumMonitors</c> with cbBuf set to zero. <c>EnumMonitors</c> fails,
/// <c>GetLastError</c> 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.
/// </para>
/// <para>
/// The buffer receives an array of <c>MONITOR_INFO_1</c> structures if Level is 1, or <c>MONITOR_INFO_2</c> structures if Level is 2.
/// </para>
/// </param>
/// <param name="cbBuf">The size, in bytes, of the buffer pointed to by pMonitors.</param>
/// <param name="pcbNeeded">
/// A pointer to a variable that receives the number of bytes copied if the function succeeds or the number of bytes required if
/// cbBuf is too small.
/// </param>
/// <param name="pcReturned">
/// A pointer to a variable that receives the number of structures that were returned in the buffer pointed to by pMonitors.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/enummonitors BOOL EnumMonitors( _In_ LPTSTR pName, _In_ DWORD Level,
// _Out_ LPBYTE pMonitors, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded, _Out_ LPDWORD pcReturned );
[DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "4d4fbed2-193f-426c-8463-eeb6b1eaf316")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumMonitors([Optional] string pName, uint Level, IntPtr pMonitors, uint cbBuf, out uint pcbNeeded, out uint pcReturned);
/// <summary>The <c>EnumMonitors</c> function retrieves information about the port monitors installed on the specified server.</summary>
/// <typeparam name="T">The type of form information to enumerate. This must be either <c>MONITOR_INFO_1</c> or <c>MONITOR_INFO_2</c>.</typeparam>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the monitors reside. If this parameter is
/// <c>NULL</c>, the local monitors are enumerated.
/// </param>
/// <returns>A sequence of <c>MONITOR_INFO_1</c> structures or <c>MONITOR_INFO_2</c> structures.</returns>
/// <exception cref="System.ArgumentException"></exception>
[PInvokeData("winspool.h", MSDNShortId = "4d4fbed2-193f-426c-8463-eeb6b1eaf316")]
public static IEnumerable<T> EnumMonitors<T>([Optional] string pName) where T : struct
{
if (!TryGetLevel<T>("MONITOR_INFO_", out var lvl))
throw new ArgumentException($"{nameof(EnumMonitors)} cannot process a structure of type {typeof(T).Name}.");
if (!EnumMonitors(pName, 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 (!EnumMonitors(pName, lvl, mem, mem.Size, out bytes, out count))
Win32Error.ThrowLastError();
return mem.ToArray<T>((int)count);
}
/// <summary>The <c>EnumPorts</c> function enumerates the ports that are available for printing on a specified server.</summary>
/// <param name="pName">
/// <para>A pointer to a null-terminated string that specifies the name of the server whose printer ports you want to enumerate.</para>
/// <para>If pName is <c>NULL</c>, the function enumerates the local machine's printer ports.</para>
/// </param>
/// <param name="Level">
/// The type of information returned in the pPorts buffer. If Level is 1, pPorts receives an array of <c>PORT_INFO_1</c> structures.
/// If Level is 2, pPorts receives an array of <c>PORT_INFO_2</c> structures.
/// </param>
/// <param name="pPorts">
/// <para>
/// A pointer to a buffer that receives an array of <c>PORT_INFO_1</c> or <c>PORT_INFO_2</c> structures. Each structure contains
/// data that describes an available printer port. The buffer must be large enough to store the strings pointed to by the structure members.
/// </para>
/// <para>
/// To determine the required buffer size, call <c>EnumPorts</c> with cbBuf set to zero. <c>EnumPorts</c> fails, <c>GetLastError</c>
/// 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.
/// </para>
/// </param>
/// <param name="cbBuf">The size, in bytes, of the buffer pointed to by pPorts.</param>
/// <param name="pcbNeeded">
/// A pointer to a variable that receives the number of bytes copied to the pPorts buffer. If the buffer is too small, the function
/// fails and the variable receives the number of bytes required.
/// </param>
/// <param name="pcReturned">
/// A pointer to a variable that receives the number of <c>PORT_INFO_1</c> or <c>PORT_INFO_2</c> structures returned in the pPorts
/// buffer. This is the number of printer ports that are available on the specified server.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>The <c>EnumPorts</c> function can succeed even if the server specified by pName does not have a printer defined.</remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/enumports BOOL EnumPorts( _In_ LPTSTR pName, _In_ DWORD Level, _Out_
// LPBYTE pPorts, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded, _Out_ LPDWORD pcReturned );
[DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "72ea0e35-bf26-4c12-9451-8f6941990d82")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumPorts([Optional] string pName, uint Level, IntPtr pPorts, uint cbBuf, out uint pcbNeeded, out uint pcReturned);
/// <summary>The <c>EnumPorts</c> function enumerates the ports that are available for printing on a specified server.</summary>
/// <typeparam name="T">The type of form information to enumerate. This must be either <c>PORT_INFO_1</c> or <c>PORT_INFO_2</c>.</typeparam>
/// <param name="pName">
/// <para>A pointer to a null-terminated string that specifies the name of the server whose printer ports you want to enumerate.</para>
/// <para>If pName is <c>NULL</c>, the function enumerates the local machine's printer ports.</para>
/// </param>
/// <returns>A sequence of <c>PORT_INFO_1</c> structures or <c>PORT_INFO_2</c> structures.</returns>
/// <remarks>The <c>EnumPorts</c> function can succeed even if the server specified by pName does not have a printer defined.</remarks>
[PInvokeData("winspool.h", MSDNShortId = "72ea0e35-bf26-4c12-9451-8f6941990d82")]
public static IEnumerable<T> EnumPorts<T>([Optional] string pName) where T : struct
{
if (!TryGetLevel<T>("PORT_INFO_", out var lvl))
throw new ArgumentException($"{nameof(EnumPorts)} cannot process a structure of type {typeof(T).Name}.");
if (!EnumPorts(pName, 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 (!EnumPorts(pName, lvl, mem, mem.Size, out bytes, out count))
Win32Error.ThrowLastError();
return mem.ToArray<T>((int)count);
}
/// <summary>The <c>EnumPrinterDrivers</c> function enumerates the printer drivers installed on a specified printer server.</summary>
/// <param name="pName">
/// <para>A pointer to a null-terminated string that specifies the name of the server on which the printer drivers are enumerated.</para>
/// <para>If pName is <c>NULL</c>, the function enumerates the local printer drivers.</para>
/// </param>
/// <param name="pEnvironment">
/// <para>
/// A pointer to a null-terminated string that specifies the environment (for example, Windows x86, Windows IA64, Windows x64, or
/// Windows NT R4000). If this parameter is <c>NULL</c>, the function uses the current environment of the caller/client (not of the destination/server).
/// </para>
/// <para>
/// If the pEnvironment string specifies "all", <c>EnumPrinterDrivers</c> enumerates printer drivers for all platforms installed on
/// the specified server.
/// </para>
/// </param>
/// <param name="Level">
/// <para>The type of information structure returned in the pDriverInfo buffer. It can be one of the following.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>1</term>
/// <term>DRIVER_INFO_1</term>
/// </item>
/// <item>
/// <term>2</term>
/// <term>DRIVER_INFO_2</term>
/// </item>
/// <item>
/// <term>3</term>
/// <term>DRIVER_INFO_3</term>
/// </item>
/// <item>
/// <term>4</term>
/// <term>DRIVER_INFO_4</term>
/// </item>
/// <item>
/// <term>5</term>
/// <term>DRIVER_INFO_5</term>
/// </item>
/// <item>
/// <term>6</term>
/// <term>DRIVER_INFO_6</term>
/// </item>
/// <item>
/// <term>8</term>
/// <term>DRIVER_INFO_8</term>
/// </item>
/// </list>
/// </param>
/// <param name="pDriverInfo">
/// <para>
/// A pointer to a buffer that receives an array of DRIVER_INFO_* structures, as specified by Level. Each structure contains data
/// that describes an available printer driver. The buffer must be large enough to receive the array of structures and any strings
/// or other data to which the structure members point.
/// </para>
/// <para>
/// To determine the required buffer size, call <c>EnumPrinterDrivers</c> with cbBuf set to zero. <c>EnumPrinterDrivers</c> fails,
/// <c>GetLastError</c> 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.
/// </para>
/// </param>
/// <param name="cbBuf">The size, in bytes, of the buffer pointed to by pDriverInfo</param>
/// <param name="pcbNeeded">
/// A pointer to a variable that receives the number of bytes copied to the pDriverInfo buffer if the function succeeds. If the
/// buffer is too small, the function fails and the variable receives the number of bytes required.
/// </param>
/// <param name="pcReturned">
/// A pointer to a variable that receives the number of structures returned in the pDriverInfo buffer. This is the number of printer
/// drivers installed on the specified print server.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/enumprinterdrivers BOOL EnumPrinterDrivers( _In_ LPTSTR pName, _In_
// LPTSTR pEnvironment, _In_ DWORD Level, _Out_ LPBYTE pDriverInfo, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded, _Out_ LPDWORD
// pcReturned );
[DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "fa3d8cf4-70bc-4362-833e-e4217ed5d43b")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumPrinterDrivers([Optional] string pName, [Optional] string pEnvironment, uint Level, IntPtr pDriverInfo, uint cbBuf, out uint pcbNeeded, out uint pcReturned);
/// <summary>The <c>EnumPrinterDrivers</c> function enumerates the printer drivers installed on a specified printer server.</summary>
/// <typeparam name="T">
/// The type of form information to enumerate. This must be either <c>DRIVER_INFO_1</c>, <c>DRIVER_INFO_2</c>, <c>DRIVER_INFO_3</c>,
/// <c>DRIVER_INFO_4</c>, <c>DRIVER_INFO_5</c>, <c>DRIVER_INFO_6</c>, or <c>DRIVER_INFO_8</c>.
/// </typeparam>
/// <param name="pName">
/// <para>A pointer to a null-terminated string that specifies the name of the server on which the printer drivers are enumerated.</para>
/// <para>If pName is <c>NULL</c>, the function enumerates the local printer drivers.</para>
/// </param>
/// <param name="pEnvironment">
/// <para>
/// A pointer to a null-terminated string that specifies the environment (for example, Windows x86, Windows IA64, Windows x64, or
/// Windows NT R4000). If this parameter is <c>NULL</c>, the function uses the current environment of the caller/client (not of the destination/server).
/// </para>
/// <para>
/// If the pEnvironment string specifies "all", <c>EnumPrinterDrivers</c> enumerates printer drivers for all platforms installed on
/// the specified server.
/// </para>
/// </param>
/// <returns>
/// A sequence of <c>DRIVER_INFO_1</c>, <c>DRIVER_INFO_2</c>, <c>DRIVER_INFO_3</c>, <c>DRIVER_INFO_4</c>, <c>DRIVER_INFO_5</c>,
/// <c>DRIVER_INFO_6</c>, or <c>DRIVER_INFO_8</c> structures.
/// </returns>
[PInvokeData("winspool.h", MSDNShortId = "fa3d8cf4-70bc-4362-833e-e4217ed5d43b")]
public static IEnumerable<T> EnumPrinterDrivers<T>([Optional] string pName, [Optional] string pEnvironment) where T : struct
{
if (!TryGetLevel<T>("DRIVER_INFO_", out var lvl))
throw new ArgumentException($"{nameof(EnumPrinterDrivers)} cannot process a structure of type {typeof(T).Name}.");
if (!EnumPrinterDrivers(pName, pEnvironment, 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 (!EnumPrinterDrivers(pName, pEnvironment, lvl, mem, mem.Size, out bytes, out count))
Win32Error.ThrowLastError();
return mem.ToArray<T>((int)count);
}
/// <summary>The <c>EnumPrintProcessorDatatypes</c> function enumerates the data types that a specified print processor supports.</summary>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the print processor resides. If this
/// parameter is <c>NULL</c>, the data types for the local print processor are enumerated.
/// </param>
/// <param name="pPrintProcessorName">
/// A pointer to a null-terminated string that specifies the name of the print processor whose data types are enumerated.
/// </param>
/// <param name="Level">The type of information returned in the pDatatypes buffer. This parameter must be 1.</param>
/// <param name="pDatatypes">
/// <para>
/// A pointer to a buffer that receives an array of <c>DATATYPES_INFO_1</c> structures. Each structure describes an available data
/// type. The buffer must be large enough to receive the array of structures and any strings or other data to which the structure
/// members point.
/// </para>
/// <para>
/// To determine the required buffer size, call <c>EnumPrintProcessorDatatypes</c> with cbBuf set to zero.
/// <c>EnumPrintProcessorDatatypes</c> fails, <c>GetLastError</c> 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.
/// </para>
/// </param>
/// <param name="cbBuf">The size, in bytes, of the buffer pointed to by pDatatypes.</param>
/// <param name="pcbNeeded">
/// A pointer to a variable that receives the number of bytes copied to the pDatatypes buffer if the function succeeds. If the
/// buffer is too small, the function fails and the variable receives the number of bytes required.
/// </param>
/// <param name="pcReturned">
/// A pointer to a variable that receives the number of structures returned in the pDatatypes buffer. This is the number of
/// supported data types.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks>
/// <para>v</para>
/// <para>Starting with Windows Vista, the data type information from remote print servers is retrieved from a local cache.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/enumprintprocessordatatypes BOOL EnumPrintProcessorDatatypes( _In_
// LPTSTR pName, _In_ LPTSTR pPrintProcessorName, _In_ DWORD Level, _Out_ LPBYTE pDatatypes, _In_ DWORD cbBuf, _Out_ LPDWORD
// pcbNeeded, _Out_ LPDWORD pcReturned );
[DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "27b6e074-d303-446b-9e5f-6cfa55c30d26")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumPrintProcessorDatatypes([Optional] string pName, string pPrintProcessorName, uint Level, IntPtr pDatatypes, uint cbBuf, out uint pcbNeeded, out uint pcReturned);
/// <summary>The <c>EnumPrintProcessorDatatypes</c> function enumerates the data types that a specified print processor supports.</summary>
/// <typeparam name="T">The type of form information to enumerate. This must be <c>DATATYPES_INFO_1</c>.</typeparam>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the print processor resides. If this
/// parameter is <c>NULL</c>, the data types for the local print processor are enumerated.
/// </param>
/// <param name="pPrintProcessorName">
/// A pointer to a null-terminated string that specifies the name of the print processor whose data types are enumerated.
/// </param>
/// <returns>A sequence of <c>DATATYPES_INFO_1</c> structures.</returns>
/// <remarks>Starting with Windows Vista, the data type information from remote print servers is retrieved from a local cache.</remarks>
[PInvokeData("winspool.h", MSDNShortId = "27b6e074-d303-446b-9e5f-6cfa55c30d26")]
public static IEnumerable<T> EnumPrintProcessorDatatypes<T>(string pPrintProcessorName, [Optional] string pName) where T : struct
{
if (!TryGetLevel<T>("DATATYPES_INFO_", out var lvl))
throw new ArgumentException($"{nameof(EnumPrintProcessorDatatypes)} cannot process a structure of type {typeof(T).Name}.");
if (!EnumPrintProcessorDatatypes(pName, pPrintProcessorName, 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 (!EnumPrintProcessorDatatypes(pName, pPrintProcessorName, lvl, mem, mem.Size, out bytes, out count))
Win32Error.ThrowLastError();
return mem.ToArray<T>((int)count);
}
/// <summary>The <c>EnumPrintProcessors</c> function enumerates the print processors installed on the specified server.</summary>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the print processors reside. If this
/// parameter is <c>NULL</c>, the local print processors are enumerated.
/// </param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment (for example, Windows x86, Windows IA64, or Windows x64).
/// If this parameter is <c>NULL</c>, the current environment of the calling application and client machine (not of the destination
/// application and print server) is used.
/// </param>
/// <param name="Level">The type of information returned in the pPrintProcessorInfo buffer. This parameter must be 1.</param>
/// <param name="pPrintProcessorInfo">
/// <para>
/// A pointer to a buffer that receives an array of <c>PRINTPROCESSOR_INFO_1</c> structures. Each structure describes an available
/// print processor. The buffer must be large enough to receive the array of structures and any strings to which the structure
/// members point.
/// </para>
/// <para>
/// To determine the required buffer size, call <c>EnumPrintProcessors</c> with cbBuf set to zero. <c>EnumPrintProcessors</c> fails,
/// <c>GetLastError</c> 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.
/// </para>
/// </param>
/// <param name="cbBuf">The size, in bytes, of the buffer pointed to by pPrintProcessorInfo.</param>
/// <param name="pcbNeeded">
/// A pointer to a variable that receives the number of bytes copied to the pPrintProcessorInfo buffer if the function succeeds. If
/// the buffer is too small, the function fails and the variable receives the number of bytes required.
/// </param>
/// <param name="pcReturned">
/// A pointer to a variable that receives the number of structures returned in the pPrintProcessorInfo buffer.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/enumprintprocessors BOOL EnumPrintProcessors( _In_ LPTSTR pName, _In_
// LPTSTR pEnvironment, _In_ DWORD Level, _Out_ LPBYTE pPrintProcessorInfo, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded, _Out_ LPDWORD
// pcReturned );
[DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "98c9185c-c89d-4b4e-8c1e-7e22b315f188")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumPrintProcessors([Optional] string pName, [Optional] string pEnvironment, uint Level, IntPtr pPrintProcessorInfo, uint cbBuf, out uint pcbNeeded, out uint pcReturned);
/// <summary>The <c>EnumPrintProcessors</c> function enumerates the print processors installed on the specified server.</summary>
/// <typeparam name="T">The type of form information to enumerate. This must be <c>PRINTPROCESSOR_INFO_1</c>.</typeparam>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the print processors reside. If this
/// parameter is <c>NULL</c>, the local print processors are enumerated.
/// </param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment (for example, Windows x86, Windows IA64, or Windows x64).
/// If this parameter is <c>NULL</c>, the current environment of the calling application and client machine (not of the destination
/// application and print server) is used.
/// </param>
/// <returns>A sequence of <c>PRINTPROCESSOR_INFO_1</c> structures.</returns>
[PInvokeData("winspool.h", MSDNShortId = "98c9185c-c89d-4b4e-8c1e-7e22b315f188")]
public static IEnumerable<T> EnumPrintProcessors<T>([Optional] string pName, [Optional] string pEnvironment) where T : struct
{
if (!TryGetLevel<T>("PRINTPROCESSOR_INFO_", out var lvl))
throw new ArgumentException($"{nameof(EnumPrintProcessors)} cannot process a structure of type {typeof(T).Name}.");
if (!EnumPrintProcessors(pName, pEnvironment, 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 (!EnumPrintProcessors(pName, pEnvironment, lvl, mem, mem.Size, out bytes, out count))
Win32Error.ThrowLastError();
return mem.ToArray<T>((int)count);
}
/// <summary>Retrieves GUID, version, and date of the specified core printer drivers and the path to their packages.</summary>
/// <param name="pszServer">
/// A pointer to a constant, null-terminated string that specifies the name of the print server. Use <c>NULL</c> for the local computer.
/// </param>
/// <param name="pszEnvironment">
/// A pointer to a constant, null-terminated string that specifies the processor architecture (for example, Windows NT x86). This
/// can be <c>NULL</c>.
/// </param>
/// <param name="pszzCoreDriverDependencies">A list of strings with the GUIDs of the core printer drivers.</param>
/// <param name="cCorePrinterDrivers">The number of strings in pszzCoreDriverDependencies.</param>
/// <param name="pCorePrinterDrivers">A pointer to an array of one or more <c>CORE_PRINTER_DRIVER</c> structures.</param>
/// <returns>
/// <para>If the operation succeeds, the return value is S_OK, otherwise the <c>HRESULT</c> will contain an error code.</para>
/// <para>For more information about COM error codes, see Error Handling.</para>
/// </returns>
/// <remarks>
/// 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.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/getcoreprinterdrivers HRESULT GetCorePrinterDrivers( _In_ LPCTSTR
// pszServer, _In_ LPCTSTR pszEnvironment, _In_ LPCTSTR pszzCoreDriverDependencies, _In_ DWORD cCorePrinterDrivers, _Out_
// PCORE_PRINTER_DRIVER pCorePrinterDrivers );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "98acad48-cd42-4d2b-be58-81c1366f6912")]
public static extern HRESULT GetCorePrinterDrivers([Optional] string pszServer, [Optional] string pszEnvironment,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NullTermStringArrayMarshaler), MarshalCookie = "Auto")] string[] pszzCoreDriverDependencies,
uint cCorePrinterDrivers, [Out] CORE_PRINTER_DRIVER[] pCorePrinterDrivers);
/// <summary>
/// The <c>GetPrinterDriver</c> function retrieves driver data for the specified printer. If the driver is not installed on the
/// local computer, <c>GetPrinterDriver</c> installs it.
/// </summary>
/// <param name="hPrinter">
/// A handle to the printer for which the driver data should be retrieved. Use the <c>OpenPrinter</c> or <c>AddPrinter</c> function
/// to retrieve a printer handle.
/// </param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment (for example, Windows x86, Windows IA64, or Windows x64).
/// If this parameter is <c>NULL</c>, the current environment of the calling application and client machine (not of the destination
/// application and print server) is used.
/// </param>
/// <param name="Level">
/// <para>The printer driver structure returned in the pDriverInfo buffer. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>1</term>
/// <term>DRIVER_INFO_1</term>
/// </item>
/// <item>
/// <term>2</term>
/// <term>DRIVER_INFO_2</term>
/// </item>
/// <item>
/// <term>3</term>
/// <term>DRIVER_INFO_3</term>
/// </item>
/// <item>
/// <term>4</term>
/// <term>DRIVER_INFO_4</term>
/// </item>
/// <item>
/// <term>5</term>
/// <term>DRIVER_INFO_5</term>
/// </item>
/// <item>
/// <term>6</term>
/// <term>DRIVER_INFO_6</term>
/// </item>
/// <item>
/// <term>8</term>
/// <term>DRIVER_INFO_8</term>
/// </item>
/// </list>
/// </param>
/// <param name="pDriverInfo">
/// <para>
/// A pointer to a buffer that receives a structure containing information about the driver, as specified by Level. The buffer must
/// be large enough to store the strings pointed to by the structure members.
/// </para>
/// <para>
/// To determine the required buffer size, call <c>GetPrinterDriver</c> with cbBuf set to zero. <c>GetPrinterDriver</c> fails,
/// <c>GetLastError</c> 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.
/// </para>
/// </param>
/// <param name="cbBuf">The size, in bytes, of the array at which pDriverInfo points.</param>
/// <param name="pcbNeeded">
/// 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.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// <para>For a non-existent driver, the function returns ERROR_UNKNOWN_PRINTER_DRIVER.</para>
/// </returns>
/// <remarks>
/// The <c>DRIVER_INFO_2</c>, <c>DRIVER_INFO_3</c>, <c>DRIVER_INFO_4</c>, <c>DRIVER_INFO_5</c>, and <c>DRIVER_INFO_6</c> structures
/// contain the file name or the full path and file name of the printer driver in the <c>pDriverPath</c> member. An application can
/// use the path and file name to load a printer driver by calling the <c>LoadLibrary</c> function and supplying the path and file
/// name as the single argument.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/getprinterdriver BOOL GetPrinterDriver( _In_ HANDLE hPrinter, _In_
// LPTSTR pEnvironment, _In_ DWORD Level, _Out_ LPBYTE pDriverInfo, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded );
[DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "93f859b4-1005-4359-8029-9536d6eeb7e7")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetPrinterDriver(HPRINTER hPrinter, [Optional] string pEnvironment, uint Level, IntPtr pDriverInfo, uint cbBuf, out uint pcbNeeded);
/// <summary>
/// The <c>GetPrinterDriver</c> function retrieves driver data for the specified printer. If the driver is not installed on the
/// local computer, <c>GetPrinterDriver</c> installs it.
/// </summary>
/// <typeparam name="T">
/// The type of driver information to enumerate. This must be either <c>DRIVER_INFO_1</c>, <c>DRIVER_INFO_2</c>,
/// <c>DRIVER_INFO_3</c>, <c>DRIVER_INFO_4</c>, <c>DRIVER_INFO_5</c>, <c>DRIVER_INFO_6</c>, or <c>DRIVER_INFO_8</c>.
/// </typeparam>
/// <param name="hPrinter">
/// A handle to the printer for which the driver data should be retrieved. Use the <c>OpenPrinter</c> or <c>AddPrinter</c> function
/// to retrieve a printer handle.
/// </param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment (for example, Windows x86, Windows IA64, or Windows x64).
/// If this parameter is <c>NULL</c>, the current environment of the calling application and client machine (not of the destination
/// application and print server) is used.
/// </param>
/// <returns>A structure containing information about the driver, as specified by <typeparamref name="T"/>.</returns>
/// <remarks>
/// The <c>DRIVER_INFO_2</c>, <c>DRIVER_INFO_3</c>, <c>DRIVER_INFO_4</c>, <c>DRIVER_INFO_5</c>, and <c>DRIVER_INFO_6</c> structures
/// contain the file name or the full path and file name of the printer driver in the <c>pDriverPath</c> member. An application can
/// use the path and file name to load a printer driver by calling the <c>LoadLibrary</c> function and supplying the path and file
/// name as the single argument.
/// </remarks>
[PInvokeData("winspool.h", MSDNShortId = "93f859b4-1005-4359-8029-9536d6eeb7e7")]
public static T GetPrinterDriver<T>(HPRINTER hPrinter, [Optional] string pEnvironment) where T : struct
{
if (!TryGetLevel<T>("DRIVER_INFO_", out var lvl))
throw new ArgumentException($"{nameof(GetPrinterDriver)} cannot process a structure of type {typeof(T).Name}.");
if (!GetPrinterDriver(hPrinter, pEnvironment, lvl, default, 0, out var sz))
Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_INSUFFICIENT_BUFFER);
using var mem = new SafeCoTaskMemHandle(sz);
if (!GetPrinterDriver(hPrinter, pEnvironment, lvl, mem, mem.Size, out sz))
Win32Error.ThrowLastError();
return mem.ToStructure<T>();
}
/// <summary>
/// The <c>GetPrinterDriver2</c> function retrieves driver data for the specified printer. If the driver is not installed on the
/// local computer, <c>GetPrinterDriver2</c> installs it and displays any user interface to the specified window.
/// </summary>
/// <param name="hWnd">
/// A handle of the window that will be used as the parent window of any user interface, such as a dialog box, that the driver
/// displays during installation. If the value of this parameter is <c>NULL</c>, the driver's user interface will still be displayed
/// to the user during installation, but it will not have a parent window.
/// </param>
/// <param name="hPrinter">
/// A handle to the printer for which the driver data should be retrieved. Use the <c>OpenPrinter</c> or <c>AddPrinter</c> function
/// to retrieve a printer handle.
/// </param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment (for example, Windows x86, Windows IA64, or Windows x64).
/// If this parameter is <c>NULL</c>, the current environment of the calling application and client machine (not of the destination
/// application and print server) is used.
/// </param>
/// <param name="Level">
/// <para>The printer driver structure returned in the pDriverInfo buffer. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>1</term>
/// <term>DRIVER_INFO_1</term>
/// </item>
/// <item>
/// <term>2</term>
/// <term>DRIVER_INFO_2</term>
/// </item>
/// <item>
/// <term>3</term>
/// <term>DRIVER_INFO_3</term>
/// </item>
/// <item>
/// <term>4</term>
/// <term>DRIVER_INFO_4</term>
/// </item>
/// <item>
/// <term>5</term>
/// <term>DRIVER_INFO_5</term>
/// </item>
/// <item>
/// <term>6</term>
/// <term>DRIVER_INFO_6</term>
/// </item>
/// <item>
/// <term>8</term>
/// <term>DRIVER_INFO_8</term>
/// </item>
/// </list>
/// </param>
/// <param name="pDriverInfo">
/// <para>
/// A pointer to a buffer that receives a structure containing information about the driver, as specified by Level. The buffer must
/// be large enough to store the strings pointed to by the structure members.
/// </para>
/// <para>
/// To determine the required buffer size, call <c>GetPrinterDriver2</c> with cbBuf set to zero. <c>GetPrinterDriver2</c> fails,
/// <c>GetLastError</c> returns <c>ERROR_INSUFFICIENT_BUFFER</c>, and the pcbNeeded parameter returns the size, in bytes, of the
/// buffer required to hold the array of structures and their data.
/// </para>
/// </param>
/// <param name="cbBuf">The size, in bytes, of the array at which pDriverInfo points.</param>
/// <param name="pcbNeeded">
/// 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.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero. To get the return status, call <c>GetLastError</c>.</para>
/// </returns>
/// <remarks>
/// <para>
/// The <c>DRIVER_INFO_2</c>, <c>DRIVER_INFO_3</c>, <c>DRIVER_INFO_4</c>, <c>DRIVER_INFO_5</c>, <c>DRIVER_INFO_6</c>, and
/// <c>DRIVER_INFO_8</c> structures contain the file name or the full path and file name of the printer driver in the
/// <c>pDriverPath</c> member. An application can use the path and file name to load a printer driver by calling the
/// <c>LoadLibrary</c> function and supplying the path and file name as the single argument.
/// </para>
/// <para>The ANSI version of this function, <c>GetPrinterDriver2A</c> is not supported and returns <c>ERROR_NOT_SUPPORTED</c>.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/getprinterdriver2 BOOL GetPrinterDriver2( _In_opt_ HWND hWnd, _In_
// HANDLE hPrinter, _In_opt_ LPTSTR pEnvironment, _In_ DWORD Level, _Out_ LPBYTE pDriverInfo, _In_ DWORD cbBuf, _Out_ LPDWORD
// pcbNeeded );
[DllImport(Lib.Winspool, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "0d482d28-7668-4734-ba71-5b355c18ddec")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetPrinterDriver2([Optional] HWND hWnd, HPRINTER hPrinter, [Optional] string pEnvironment, uint Level, IntPtr pDriverInfo, uint cbBuf, out uint pcbNeeded);
/// <summary>
/// The <c>GetPrinterDriver2</c> function retrieves driver data for the specified printer. If the driver is not installed on the
/// local computer, <c>GetPrinterDriver2</c> installs it and displays any user interface to the specified window.
/// </summary>
/// <typeparam name="T">
/// The type of driver information to enumerate. This must be either <c>DRIVER_INFO_1</c>, <c>DRIVER_INFO_2</c>,
/// <c>DRIVER_INFO_3</c>, <c>DRIVER_INFO_4</c>, <c>DRIVER_INFO_5</c>, <c>DRIVER_INFO_6</c>, or <c>DRIVER_INFO_8</c>.
/// </typeparam>
/// <param name="hPrinter">
/// A handle to the printer for which the driver data should be retrieved. Use the <c>OpenPrinter</c> or <c>AddPrinter</c> function
/// to retrieve a printer handle.
/// </param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment (for example, Windows x86, Windows IA64, or Windows x64).
/// If this parameter is <c>NULL</c>, the current environment of the calling application and client machine (not of the destination
/// application and print server) is used.
/// </param>
/// <param name="hWnd">
/// A handle of the window that will be used as the parent window of any user interface, such as a dialog box, that the driver
/// displays during installation. If the value of this parameter is <c>NULL</c>, the driver's user interface will still be displayed
/// to the user during installation, but it will not have a parent window.
/// </param>
/// <returns>A structure containing information about the driver, as specified by <typeparamref name="T"/>.</returns>
/// <exception cref="System.ArgumentException"></exception>
/// <remarks>
/// <para>
/// The <c>DRIVER_INFO_2</c>, <c>DRIVER_INFO_3</c>, <c>DRIVER_INFO_4</c>, <c>DRIVER_INFO_5</c>, <c>DRIVER_INFO_6</c>, and
/// <c>DRIVER_INFO_8</c> structures contain the file name or the full path and file name of the printer driver in the
/// <c>pDriverPath</c> member. An application can use the path and file name to load a printer driver by calling the
/// <c>LoadLibrary</c> function and supplying the path and file name as the single argument.
/// </para>
/// <para>The ANSI version of this function, <c>GetPrinterDriver2A</c> is not supported and returns <c>ERROR_NOT_SUPPORTED</c>.</para>
/// </remarks>
[PInvokeData("winspool.h", MSDNShortId = "0d482d28-7668-4734-ba71-5b355c18ddec")]
public static T GetPrinterDriver2<T>(HPRINTER hPrinter, [Optional] string pEnvironment, [Optional] HWND hWnd) where T : struct
{
if (!TryGetLevel<T>("DRIVER_INFO_", out var lvl))
throw new ArgumentException($"{nameof(GetPrinterDriver2)} cannot process a structure of type {typeof(T).Name}.");
if (!GetPrinterDriver2(hWnd, hPrinter, pEnvironment, lvl, default, 0, out var sz))
Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_INSUFFICIENT_BUFFER);
using var mem = new SafeCoTaskMemHandle(sz);
if (!GetPrinterDriver2(hWnd, hPrinter, pEnvironment, lvl, mem, mem.Size, out sz))
Win32Error.ThrowLastError();
return mem.ToStructure<T>();
}
/// <summary>The <c>GetPrinterDriverDirectory</c> function retrieves the path of the printer-driver directory.</summary>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server on which the printer driver resides. If this
/// parameter is <c>NULL</c>, the local driver-directory path is retrieved.
/// </param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment (for example, Windows x86, Windows IA64, or Windows x64).
/// If this parameter is <c>NULL</c>, the current environment of the calling application and client machine (not of the destination
/// application and print server) is used.
/// </param>
/// <param name="Level">The structure level. This value must be 1.</param>
/// <param name="pDriverDirectory">A pointer to a buffer that receives the path.</param>
/// <param name="cbBuf">The size of the buffer to which pDriverDirectory points.</param>
/// <param name="pcbNeeded">
/// 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.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/getprinterdriverdirectory BOOL GetPrinterDriverDirectory( _In_ LPTSTR
// pName, _In_ LPTSTR pEnvironment, _In_ DWORD Level, _Out_ LPBYTE pDriverDirectory, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "69c9cc87-d7e3-496a-b631-b3ae30cdb3fd")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetPrinterDriverDirectory([Optional] string pName, [Optional] string pEnvironment, uint Level, StringBuilder pDriverDirectory, int cbBuf, out int pcbNeeded);
/// <summary>Retrieves the path to the specified printer driver package on a print server.</summary>
/// <param name="pszServer">
/// A pointer to a constant, null-terminated string that specifies the name of the print server. Use <c>NULL</c> for the local computer.
/// </param>
/// <param name="pszEnvironment">
/// A pointer to a constant, null-terminated string that specifies the processor architecture (for example, Windows NT x86). This
/// can be <c>NULL</c>.
/// </param>
/// <param name="pszLanguage">
/// A pointer to a constant, null-terminated string that specifies the Multilingual User Interface language for the driver being
/// installed. This can be <c>NULL</c>.
/// </param>
/// <param name="pszPackageID">A pointer to a constant, null-terminated string that specifies the ID of the driver package.</param>
/// <param name="pszDriverPackageCab">
/// A pointer to a null-terminated string that specifies the path to the cabinet file for the driver package. This can be
/// <c>NULL</c>. See Remarks.
/// </param>
/// <param name="cchDriverPackageCab">The size, in characters, of the pszDriverPackageCab buffer. This can be <c>NULL</c>.</param>
/// <param name="pcchRequiredSize">A pointer to the required size of the pszDriverPackageCab buffer.</param>
/// <returns>
/// <para>If the operation succeeds, the return value is S_OK, otherwise the <c>HRESULT</c> will contain an error code.</para>
/// <para>For more information about COM error codes, see Error Handling.</para>
/// </returns>
/// <remarks>
/// <para>
/// To obtain a value for cchDriverPackageCab, call the function with <c>NULL</c> as the value of pszDriverPackageCab. Use the value
/// returned in pcchRequiredSize as the value of cchDriverPackageCab and call the function again.
/// </para>
/// <para>The pszPackageID is typically obtained from a call to <c>GetCorePrinterDrivers</c>.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/getprinterdriverpackagepath HRESULT GetPrinterDriverPackagePath( _In_
// LPCTSTR pszServer, _In_ LPCTSTR pszEnvironment, _In_ LPCTSTR pszLanguage, _In_ LPCTSTR pszPackageID, _Inout_ LPTSTR
// pszDriverPackageCab, _In_ DWORD cchDriverPackageCab, _Out_ LPDWORD pcchRequiredSize );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "e88e984b-d2c0-43b4-8f70-b05ec202ab14")]
public static extern HRESULT GetPrinterDriverPackagePath([Optional] string pszServer, [Optional] string pszEnvironment, [Optional] string pszLanguage, string pszPackageID, StringBuilder pszDriverPackageCab, int cchDriverPackageCab, out int pcchRequiredSize);
/// <summary>
/// The <c>GetPrintProcessorDirectory</c> function retrieves the path to the print processor directory on the specified server.
/// </summary>
/// <param name="pName">
/// A pointer to a null-terminated string that specifies the name of the server. If this parameter is <c>NULL</c>, a local path is returned.
/// </param>
/// <param name="pEnvironment">
/// A pointer to a null-terminated string that specifies the environment (for example, Windows x86, Windows IA64, or Windows x64).
/// If this parameter is <c>NULL</c>, the current environment of the calling application and client machine (not of the destination
/// application and print server) is used.
/// </param>
/// <param name="Level">The structure level. This value must be 1.</param>
/// <param name="pPrintProcessorInfo">
/// A pointer to a buffer that receives the path. Note that, for operating systems prior to Windows Server 2003 SP 1, the path is in
/// the local format for the server, not the true remote format. For example, the path is given as
/// "%Windir%\System32\Spool\Prtprocs\%Environment%" instead of "\\ServerName\Print$\Prtprocs\%Environment%", even when called for a
/// remote server. For the operating systems Windows Server 2003 SP 1 and later, the true remote path is returned.
/// </param>
/// <param name="cbBuf">The size of the buffer pointed to by pPrintProcessorInfo.</param>
/// <param name="pcbNeeded">
/// 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.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is a nonzero value.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
/// <remarks/>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/getprintprocessordirectory BOOL GetPrintProcessorDirectory( _In_ LPTSTR
// pName, _In_ LPTSTR pEnvironment, _In_ DWORD Level, _Out_ LPBYTE pPrintProcessorInfo, _In_ DWORD cbBuf, _Out_ LPDWORD pcbNeeded );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "a2443cfd-e5ba-41c6-aaf4-45051a3d0e26")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetPrintProcessorDirectory([Optional] string pName, [Optional] string pEnvironment, uint Level, StringBuilder pPrintProcessorInfo, int cbBuf, out int pcbNeeded);
/// <summary>Installs a printer driver from a driver package that is in the print server's driver store.</summary>
/// <param name="pszServer">
/// A pointer to a constant, null-terminated string that specifies the name of the print server. <c>NULL</c> means the local computer.
/// </param>
/// <param name="pszInfPath">
/// A pointer to a constant, null-terminated string that specifies the driver store path to the print driver's .inf file.
/// <c>NULL</c> means the driver is in an inf file that shipped with Windows.
/// </param>
/// <param name="pszDriverName">A pointer to a constant, null-terminated string that specifies the name of the driver.</param>
/// <param name="pszEnvironment">
/// A pointer to a constant, null-terminated string that specifies the processor architecture (for example, Windows NT x86). This
/// can be <c>NULL</c>.
/// </param>
/// <param name="dwFlags">
/// This can only be 0 or IPDFP_COPY_ALL_FILES. A value of 0 means that the printer driver must be added and any files in the
/// printer driver directory that are newer than corresponding files currently in use must be copied. A value of
/// IPDFP_COPY_ALL_FILES means the printer driver and all the files in the printer driver directory must be added. The file time
/// stamps are ignored when dwFlags has a value of IPDFP_COPY_ALL_FILES.
/// </param>
/// <returns>
/// <para>If the operation succeeds, the return value is S_OK, otherwise the <c>HRESULT</c> will contain an error code.</para>
/// <para>For more information about COM error codes, see Error Handling.</para>
/// </returns>
/// <remarks>
/// <para>The driver store is typically either %windir%\inf or %windir%\System32\DriverStore\FileRepository.</para>
/// <para><c>InstallPrinterDriverFromPackage</c> also installs other files in the package, such as color profiles and print processors.</para>
/// <para>
/// Users must have printer administration rights to install either on a remote computer or on the local computer when the user is
/// logged in with Terminal Services.
/// </para>
/// <para>Only signed packages can be installed on a remote computer.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/installprinterdriverfrompackage HRESULT InstallPrinterDriverFromPackage(
// _In_ LPCTSTR pszServer, _In_ LPCTSTR pszInfPath, _In_ LPCTSTR pszDriverName, _In_ LPCTSTR pszEnvironment, _In_ DWORD dwFlags );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "5906d9c6-9fbf-4ec6-81ce-112a9ef6d7c0")]
public static extern HRESULT InstallPrinterDriverFromPackage([Optional] string pszServer, [Optional] string pszInfPath, string pszDriverName, [Optional] string pszEnvironment, uint dwFlags);
/// <summary>Uploads a printer driver to the print server's driver store so that it can be installed by calling <c>InstallPrinterDriverFromPackage</c>.</summary>
/// <param name="pszServer">
/// A pointer to a constant, null-terminated string that specifies the name of the print server. Use <c>NULL</c> if the server is
/// the local computer.
/// </param>
/// <param name="pszInfPath">
/// A pointer to a constant ,null-terminated string that specifies the source path to the driver's .inf file.
/// </param>
/// <param name="pszEnvironment">
/// A pointer to a constant, null-terminated string that specifies the server's processor architecture (for example, Windows NT
/// x86). This can be <c>NULL</c>.
/// </param>
/// <param name="dwFlags">
/// <para>This can be any of the following values:</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>UPDP_SILENT_UPLOAD</term>
/// <term>The UI will not be shown during the upload.</term>
/// </item>
/// <item>
/// <term>UPDP_UPLOAD_ALWAYS</term>
/// <term>The files will be uploaded even if the package is already in the server's driver store.</term>
/// </item>
/// <item>
/// <term>UPDP_CHECK_DRIVERSTORE</term>
/// <term>
/// The server's driver store will be checked before upload to see if the package is already there. This setting is ignored if
/// UPDP_UPLOAD_ALWAYS is set.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="hwnd">A handle to the copying user interface.</param>
/// <param name="pszDestInfPath">A pointer to the destination path, in the driver store, to which the driver's .inf file was copied.</param>
/// <param name="pcchDestInfPath">
/// On input, specifies the size, in characters, of the pszDestInfPath buffer. On output, receives the size, in characters, of the
/// path string, including the terminating null character.
/// </param>
/// <returns>
/// <para>If the operation succeeds, the return value is S_OK, otherwise the <c>HRESULT</c> will contain an error code.</para>
/// <para>For more information about COM error codes, see Error Handling.</para>
/// </returns>
/// <remarks>
/// <para>The driver store is typically either %windir%\inf or %windir%\System32\DriverStore\FileRepository.</para>
/// <para>Only one package at a time can be uploaded. If a package is dependent on others, they must be uploaded separately.</para>
/// <para>Only signed driver packages can be uploaded.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/printdocs/uploadprinterdriverpackage HRESULT UploadPrinterDriverPackage( _In_
// LPCTSTR pszServer, _In_ LPCTSTR pszInfPath, _In_ LPCTSTR pszEnvironment, _In_ DWORD dwFlags, _In_ HWND hwnd, _Out_ LPTSTR
// pszDestInfPath, _Inout_ PULONG pcchDestInfPath );
[DllImport(Lib.Winspool, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("winspool.h", MSDNShortId = "dd3b3a3b-8ded-44ae-85dd-e630bc62e898")]
public static extern HRESULT UploadPrinterDriverPackage([Optional] string pszServer, string pszInfPath, [Optional] string pszEnvironment, UPDP dwFlags, HWND hwnd, StringBuilder pszDestInfPath, ref uint pcchDestInfPath);
}
}