[DllImport("winspool.drv", CharSet=CharSet.Auto, SetLastError=true)]
static extern int GetPrinterDriver(IntPtr hPrinter, string pEnvironment, uint Level, IntPtr pDriverInfo, uint cbBuf, out uint pcbNeeded);
As always, only do SetLastError=true if you actually intend to call GetLastError.
Please add some!
[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int GetPrinterDriver(IntPtr hPrinter, string pEnvironment, uint Level, IntPtr pDriverInfo,
int cbBuf, out int pcbNeeded);
/// <summary>
/// The .NET definition of the win32 DRIVER_INFO_8 structure.
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal class DRIVER_INFO_8
{
public uint cVersion;
[MarshalAs(UnmanagedType.LPTStr)]
public string pName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pEnvironment;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDriverPath;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDataFile;
[MarshalAs(UnmanagedType.LPTStr)]
public string pConfigFile;
[MarshalAs(UnmanagedType.LPTStr)]
public string pHelpFile;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDependentFiles;
[MarshalAs(UnmanagedType.LPTStr)]
public string pMonitorName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pDefaultDataType;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszzPreviousNames;
public ComTypes.FILETIME ftDriverDate;
public UInt64 dwlDriverVersion;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszMfgName;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszOEMUrl;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszHardwareID;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszProvider;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszPrintProcessor;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszVendorSetup;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszzColorProfiles;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszInfPath;
public uint dwPrinterDriverAttributes;
[MarshalAs(UnmanagedType.LPTStr)]
public string pszzCoreDriverDependencies;
public ComTypes.FILETIME ftMinInboxDriverVerDate;
public UInt64 dwlMinInboxDriverVerVersion;
}
/// <summary>
/// This returns the data type to use so that we can just throw bytes at the printer. Recent printer drivers use
/// the XPS driver model and require the data type to be XPS_PASS. For older drivers the data type needs to be
/// RAW.
/// </summary>
/// <param name="printerHandle">The handle to a printer, returned by OpenPrinter.</param>
/// <param name="dataType">The returned data type, XPS_PASS or RAW.</param>
/// <returns>true if successful, otherwise false.</returns>
private static bool GetDataType(IntPtr printerHandle, out string dataType)
{
IntPtr driverInfo = new IntPtr(0);
int needed;
DRIVER_INFO_8 driverInfo8;
dataType = null;
// The first call to GetPrinterDriver is just to get the buffer length required
if (NativeMethods.GetPrinterDriver(printerHandle, null, 8, driverInfo, 0, out needed) != 0)
{
// There's something wrong if the above call doesn't fail with a zero length buffer
return false;
}
if (Marshal.GetLastWin32Error() != 122) // ERROR_INSUFFICIENT_BUFFER
{
return false;
}
try
{
driverInfo = Marshal.AllocHGlobal(needed);
if (NativeMethods.GetPrinterDriver(printerHandle, null, 8, driverInfo, needed, out needed) == 0)
{
return false;
}
driverInfo8 = (DRIVER_INFO_8)Marshal.PtrToStructure(driverInfo, typeof(DRIVER_INFO_8));
dataType = (driverInfo8.dwPrinterDriverAttributes & 2) == 2 ? "XPS_PASS" : "RAW"; // 2 = PRINTER_DRIVER_XPS
return true;
}
finally
{
Marshal.FreeHGlobal(driverInfo);
}
}
Do you know one? Please contribute it!