/// <summary> /// Constructs a new PrintTicket provider instance for the given device. /// </summary> /// <param name="deviceName">name of printer device the provider should be bound to</param> /// <param name="maxVersion">max schema version supported by client</param> /// <param name="clientVersion">schema version requested by client</param> /// <exception cref="PrintQueueException"> /// The FallbackPTProvider instance failed to bind to the specified printer. /// </exception> public FallbackPTProvider(string deviceName, int maxVersion, int clientVersion) { Toolbox.EmitEvent(EventTrace.Event.WClientDRXPTProviderStart); // We are not doing late binding to the device here because we should // indicate right away if there was an error in binding the provider // to the device. Doing late binding would mean that any instance // method could throw a no such printer exception. if (false == UnsafeNativeMethods.OpenPrinterW(deviceName, out this._deviceHandle, new HandleRef(this, IntPtr.Zero))) { throw new PrintQueueException(Marshal.GetLastWin32Error(), "PrintConfig.Provider.BindFail", deviceName); } try { PRINTER_INFO_2 info = GetPrinterInfo2W(); this._deviceName = info.pPrinterName; this._driverName = info.pDriverName; this._portName = info.pPortName; if (info.pDevMode != null) { this._driverVersion = info.pDevMode.DriverVersion; } } catch (Win32Exception win32Exception) { throw new PrintQueueException(win32Exception.ErrorCode, "PrintConfig.Provider.BindFail", deviceName, win32Exception); } Toolbox.EmitEvent(EventTrace.Event.WClientDRXPTProviderEnd); }
///<summary> /// Obtain a DEVMODE from a printer ///</summary> ///<param name="pHandle">Printer handle</param> ///<param name="baseType">Type of DEVMODE (printer default or user default)</param> ///<param name="devModeBytes">DEVMODE bytes</param> ///<returns>False if the call fails</returns> private DevMode GetDEVMODE(BaseDevModeType baseType) { DevMode result; switch (baseType) { case BaseDevModeType.PrinterDefault: { PRINTER_INFO_2 info = GetPrinterInfo2W(); result = info.pDevMode; break; } case BaseDevModeType.UserDefault: { PRINTER_INFO_8_AND_9 info = GetPrinterInfo8Or9W(true); if (info.pDevMode != null) { result = info.pDevMode; } else { // No user default devmode, try the printer default, which is // effectively the user default if their isn't a per user default // overriding it. result = GetDEVMODE(BaseDevModeType.PrinterDefault); } break; } default: { throw new ArgumentOutOfRangeException("baseType"); } } if (result == null) { throw new PrintSystemException(); } return(result); }
/// <summary> /// A callback that copies PRINTER_INFO_2 fields from an unmanaged buffer /// </summary> public void Callback(HGlobalBuffer pPrinterBuffer) { // PRINTER_INFO_2 layout from http://msdn.microsoft.com/en-us/library/dd162845(VS.85).aspx // //typedef struct _PRINTER_INFO_2 { // LPTSTR pServerName; // LPTSTR pPrinterName; // LPTSTR pShareName; // LPTSTR pPortName; // LPTSTR pDriverName; // LPTSTR pComment; // LPTSTR pLocation; // LPDEVMODE pDevMode; // LPTSTR pSepFile; // LPTSTR pPrintProcessor; // LPTSTR pDatatype; // LPTSTR pParameters; // PSECURITY_DESCRIPTOR pSecurityDescriptor; // DWORD Attributes; // DWORD Priority; // DWORD DefaultPriority; // DWORD StartTime; // DWORD UntilTime; // DWORD Status; // DWORD cJobs; // DWORD AveragePPM; // } PRINTER_INFO_2, *PPRINTER_INFO_2; PRINTER_INFO_2 = new PRINTER_INFO_2(); bool shouldRelease = false; pPrinterBuffer.Handle.DangerousAddRef(ref shouldRelease); try { IntPtr ptr = pPrinterBuffer.Handle.DangerousGetHandle(); // LPTSTR pPrinterName; IntPtr pPrinterName = Marshal.ReadIntPtr(ptr, 1 * Marshal.SizeOf(typeof(IntPtr))); if (pPrinterName != IntPtr.Zero) { PRINTER_INFO_2.pPrinterName = Marshal.PtrToStringUni(pPrinterName); } // LPTSTR pPortName; IntPtr pPortName = Marshal.ReadIntPtr(ptr, 3 * Marshal.SizeOf(typeof(IntPtr))); if (pPortName != IntPtr.Zero) { PRINTER_INFO_2.pPortName = Marshal.PtrToStringUni(pPortName); } // LPTSTR pDriverName; IntPtr pDriverName = Marshal.ReadIntPtr(ptr, 4 * Marshal.SizeOf(typeof(IntPtr))); if (pDriverName != IntPtr.Zero) { PRINTER_INFO_2.pDriverName = Marshal.PtrToStringUni(pDriverName); } // LPDEVMODE pDevMode; IntPtr pDevMode = Marshal.ReadIntPtr(ptr, 7 * Marshal.SizeOf(typeof(IntPtr))); if (pDevMode != IntPtr.Zero) { PRINTER_INFO_2.pDevMode = DevMode.FromIntPtr(pDevMode); } } finally { if (shouldRelease) { pPrinterBuffer.Handle.DangerousRelease(); } } }