/// <summary> /// Merges delta PrintTicket with base PrintTicket and then validates the merged PrintTicket. /// </summary> /// <param name="basePrintTicket">The MemoryStream that contains base XML PrintTicket.</param> /// <param name="deltaPrintTicket">The MemoryStream that contains delta XML PrintTicket.</param> /// <param name="scope">scope that delta PrintTicket and result PrintTicket will be limited to</param> /// <param name="conflictStatus">The returned conflict resolving status.</param> /// <returns>MemoryStream that contains validated and merged PrintTicket XML.</returns> /// <exception cref="ObjectDisposedException"> /// The PTProvider instance has already been disposed. /// </exception> /// <exception cref="ArgumentException"> /// The base PrintTicket specified by <paramref name="basePrintTicket"/> is not well-formed, /// or delta PrintTicket specified by <paramref name="deltaPrintTicket"/> is not well-formed. /// </exception> /// <exception cref="PrintQueueException"> /// The PTProvider instance failed to merge and validate the input PrintTicket(s). /// </exception> public override MemoryStream MergeAndValidatePrintTicket(MemoryStream basePrintTicket, MemoryStream deltaPrintTicket, PrintTicketScope scope, out ConflictStatus conflictStatus) { VerifyAccess(); DevModeFields supportedFields = DevModeFields.All; DevMode defaultDevMode = GetDEVMODE(BaseDevModeType.PrinterDefault); InternalPrintTicket baseTicket = (basePrintTicket != null) ? new InternalPrintTicket(basePrintTicket) : null; DevMode baseDevMode = defaultDevMode.Clone(); PrintTicketToDevMode(baseDevMode, baseTicket, scope, supportedFields); InternalPrintTicket deltaTicket = (deltaPrintTicket != null) ? new InternalPrintTicket(deltaPrintTicket) : null; DevMode deltaDevMode = defaultDevMode.Clone(); PrintTicketToDevMode(deltaDevMode, deltaTicket, scope, supportedFields); // DevMode Merge - Copy fields set in baseDevMode but not set in deltaDevMode deltaDevMode.Copy(baseDevMode, baseDevMode.Fields & (~deltaDevMode.Fields)); conflictStatus = Validate(deltaDevMode) ? ConflictStatus.NoConflict : ConflictStatus.ConflictResolved; InternalPrintTicket validatedTicket = DevModeToPrintTicket(deltaDevMode, scope, supportedFields); return(validatedTicket.XmlStream); }
private bool Validate(DevMode devMode) { bool settingsChanged = false; // Create a copy of the devmode before validating... if anything // changes, then we'll report it DevMode originalDevMode = devMode.Clone(); // Validate the DEVMODE via a call to the driver. SetDocumentProperties(devMode.ByteData, true); // Compare the devmods to decide whether any features // changed. Ignore changes in the DM_FORMNAME field // because the shim may clear it in selecting a paper size. // If other paper size fields are set in the DEVMODE, ignore the form field // because some driver change set / clear the form field during DocumentProperties // without actually changing the selected paper size. if (originalDevMode.IsAnyFieldSet(DevModeFields.DM_PAPERWIDTH | DevModeFields.DM_PAPERLENGTH | DevModeFields.DM_PAPERSIZE)) { originalDevMode.Fields &= ~DevModeFields.DM_FORMNAME; originalDevMode.Fields |= devMode.Fields & DevModeFields.DM_FORMNAME; originalDevMode.FormName = devMode.FormName; } // Ignore device name in the original DEVMODE. Copy the full buffer so that any extra // garbage in the device name after the string also matches. The device name isn't actually // a setting per-se. Version changes should be noted, because the same content may mean different // things in different versions of a driver. originalDevMode.DeviceName = devMode.DeviceName; // Do the actual comparison. Note that if there are issues in the private DEVMODE similar // to the issues fixed up in the public DEVMODE, there may be false positive return values // from this API. There's no way to fix this issue. for (int i = 0; i < originalDevMode.ByteData.Length; i++) { if (originalDevMode.ByteData[i] != devMode.ByteData[i]) { settingsChanged = true; } } WinSpoolPrinterCapabilities capabilities = GetCapabilities(null); try { PrintSchemaShim.PruneFeatures(devMode, capabilities); } finally { capabilities.Release(); } return(settingsChanged); }
/// <summary> /// Gets the PrintCapabilities relative to the given PrintTicket. /// </summary> /// <param name="printTicket">The stream that contains XML PrintTicket based on which PrintCapabilities should be built.</param> /// <returns>Stream that contains XML PrintCapabilities.</returns> /// <exception cref="ObjectDisposedException"> /// The PTProvider instance has already been disposed. /// </exception> /// <exception cref="ArgumentException"> /// The input PrintTicket specified by <paramref name="printTicket"/> is not well-formed. /// </exception> /// <exception cref="PrintQueueException"> /// The PTProvider instance failed to retrieve the PrintCapabilities. /// </exception> public override MemoryStream GetPrintCapabilities(MemoryStream printTicket) { VerifyAccess(); InternalPrintTicket internalTicket = null; try { internalTicket = (printTicket != null) ? new InternalPrintTicket(printTicket) : null; } catch (XmlException xmlException) { throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, "{0} {1} {2}", PrintSchemaTags.Framework.PrintTicketRoot, PTUtility.GetTextFromResource("FormatException.XMLNotWellFormed"), xmlException.Message), "printTicket", xmlException); } DevMode defaultDevMode = GetDEVMODE(BaseDevModeType.UserDefault); DevMode devMode = defaultDevMode.Clone(); PrintTicketToDevMode(devMode, internalTicket, PrintTicketScope.JobScope, DevModeFields.All); MemoryStream capabilitiesStream = new MemoryStream(); WinSpoolPrinterCapabilities capabilities = GetCapabilities(devMode); try { PrintCapabilitiesWriter writer = new PrintCapabilitiesWriter(capabilitiesStream, "ns0000", this.OemDriverNamespace, false); try { writer.WriteStartDocument(); { writer.WritePageDevmodeSnapshot(devMode.ByteData); if (capabilities.HasICMIntent) { writer.WritePageICMRenderingIntentFeature(); } if (capabilities.HasICMMethod) { writer.WritePageColorManagementFeature(); } if (capabilities.CanCollate) { writer.WriteDocumentCollateFeature(); } int minCopies = capabilities.MinCopies; int maxCopies = capabilities.MaxCopies; int defaultCopies = minCopies; defaultCopies = Math.Max(minCopies, Math.Min(defaultDevMode.Copies, maxCopies)); writer.WriteJobCopiesAllDocumentsParameterDef(minCopies, maxCopies, defaultCopies); writer.WriteJobNUpAllDocumentsContiguously(capabilities.NUp); writer.WriteJobDuplexAllDocumentsContiguouslyFeature(capabilities.CanDuplex); if (capabilities.CanScale) { writer.WritePageScalingFeature(1, 1000, 100); } writer.WritePageMediaSizeFeature( capabilities.Papers, capabilities.PaperNames, PrintSchemaShim.TenthOfMillimeterToMicrons(capabilities.PaperSizes) ); writer.WritePageResolutionFeature(capabilities.Resolutions); int logicalPixelsX, logicalPixelsY; int physicalWidth, physicalHeight; int physicalOffsetX, physicalOffsetY; int horizontalResolution, verticalResolution; bool gotDevCaps = capabilities.TryGetDeviceCapabilities( out logicalPixelsX, out logicalPixelsY, out physicalWidth, out physicalHeight, out physicalOffsetX, out physicalOffsetY, out horizontalResolution, out verticalResolution); if (gotDevCaps && logicalPixelsX > 0 && logicalPixelsY > 0) { int imageableSizeWidth = PrintSchemaShim.DpiToMicrons(physicalWidth, logicalPixelsX); int imageableSizeHeight = PrintSchemaShim.DpiToMicrons(physicalHeight, logicalPixelsY); int originWidth = PrintSchemaShim.DpiToMicrons(physicalOffsetX, logicalPixelsY); int originHeight = PrintSchemaShim.DpiToMicrons(physicalOffsetY, logicalPixelsY); int extentWidth = PrintSchemaShim.DpiToMicrons(horizontalResolution, logicalPixelsY); int extentHeight = PrintSchemaShim.DpiToMicrons(verticalResolution, logicalPixelsY); writer.WritePageImageableSizeProperty( imageableSizeWidth, imageableSizeHeight, originWidth, originHeight, extentWidth, extentHeight); } writer.WritePageOrientationFeature(capabilities.LandscapeOrientation); writer.WritePageOutputColorFeature(capabilities.HasColor); writer.WriteJobInputBinFeature(capabilities.Bins, capabilities.BinNames); writer.WritePageMediaTypeFeature(capabilities.MediaTypes, capabilities.MediaTypeNames); if (capabilities.TrueType) { writer.WritePageTrueTypeFontModeFeature(); writer.WritePageDeviceFontSubstitutionFeature(); } } writer.WriteEndDocument(); } finally { writer.Release(); writer = null; } } finally { capabilities.Release(); capabilities = null; } // calls Security Critical Dispose on a private resource capabilitiesStream.Position = 0; return(capabilitiesStream); }