Example #1
0
        /// <summary>
        /// Creates a COM stream over HGlobal allocated memory
        /// </summary>
        /// <param name="hGlobal">HGlobal to create stream over, IntPtr.Zero to auto allocate memory</param>
        /// <param name="fDeleteOnRelease">Delete the allocated memory when the stream is released</param>
        /// <param name="ppstm">Created Stream</param>
        /// <returns>HRESULT</returns>
        private static IStream CreateStreamOnHGlobal()
        {
            IStream result;

            uint hResult = UnsafeNativeMethods.CreateStreamOnHGlobal(SafeMemoryHandle.Wrap(IntPtr.Zero), true, out result);

            if (!PTUtility.IsSuccessCode(hResult))
            {
                Marshal.ThrowExceptionForHR((int)hResult);
            }

            return(result);
        }
Example #2
0
        /// <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>
        /// <exception cref="PrintingNotSupportedException">
        /// Printing components are not installed on the client
        /// </exception>
        public override MemoryStream GetPrintCapabilities(MemoryStream printTicket)
        {
            VerifyAccess();

            IStream printCapabilitiesStream = CreateStreamOnHGlobal();

            try
            {
                IStream printTicketStream = IStreamFromMemoryStream(printTicket);
                try
                {
                    string errorMsg;
                    // What happens if the native code returns a iStreamLength that is too long?
                    // One option is we trust providers and don't do run-time check.
                    uint hResult = UnsafeNativeMethods.PTGetPrintCapabilities(_providerHandle, printTicketStream, printCapabilitiesStream, out errorMsg);
                    if (PTUtility.IsSuccessCode(hResult))
                    {
                        RewindIStream(printCapabilitiesStream);
                        return(MemoryStreamFromIStream(printCapabilitiesStream));
                    }

                    if (hResult == (uint)NativeErrorCode.E_PRINTTICKET_FORMAT)
                    {
                        throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
                                                                  "{0} {1} {2}",
                                                                  PrintSchemaTags.Framework.PrintTicketRoot,
                                                                  PTUtility.GetTextFromResource("FormatException.XMLNotWellFormed"),
                                                                  errorMsg),
                                                    "printTicket");
                    }
                    else
                    {
                        throw new PrintQueueException((int)hResult,
                                                      "PrintConfig.Provider.GetPrintCapFail",
                                                      _deviceName,
                                                      errorMsg);
                    }
                }
                finally
                {
                    DeleteIStream(ref printTicketStream);
                }
            }
            finally
            {
                DeleteIStream(ref printCapabilitiesStream);
            }
        }
Example #3
0
        /// <summary>
        /// Converts the given Win32 DEVMODE into PrintTicket.
        /// </summary>
        /// <param name="devMode">Byte buffer containing the Win32 DEVMODE.</param>
        /// <param name="scope">scope that the result PrintTicket will be limited to</param>
        /// <returns>MemoryStream that contains the converted XML PrintTicket.</returns>
        /// <exception cref="ObjectDisposedException">
        /// The PTProvider instance has already been disposed.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The DEVMODE specified by <paramref name="devMode"/> is not well-formed.
        /// </exception>
        /// <exception cref="PrintQueueException">
        /// The PTProvider instance failed to convert the DEVMODE to a PrintTicket.
        /// </exception>
        /// <exception cref="PrintingNotSupportedException">
        /// Printing components are not installed on the client
        /// </exception>
        public override MemoryStream ConvertDevModeToPrintTicket(byte[] devMode,
                                                                 PrintTicketScope scope)
        {
            VerifyAccess();

            IntPtr umDevMode = Marshal.AllocCoTaskMem(devMode.Length);

            try
            {
                // Allocate unmanaged buffer and copy devMode byte array into the unmanaged buffer
                Marshal.Copy(devMode, 0, umDevMode, devMode.Length);

                IStream printTicketStream = CreateStreamOnHGlobal();
                try
                {
                    uint hResult = UnsafeNativeMethods.PTConvertDevModeToPrintTicket(_providerHandle,
                                                                                     (uint)devMode.Length,
                                                                                     new HandleRef(this, umDevMode),
                                                                                     (uint)scope,
                                                                                     printTicketStream);

                    if (PTUtility.IsSuccessCode(hResult))
                    {
                        RewindIStream(printTicketStream);
                        return(MemoryStreamFromIStream(printTicketStream));
                    }

                    throw new PrintQueueException((int)hResult,
                                                  "PrintConfig.Provider.DevMode2PTFail",
                                                  _deviceName);
                }
                finally
                {
                    DeleteIStream(ref printTicketStream);
                }
            }
            finally
            {
                if (umDevMode != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(umDevMode);
                    umDevMode = IntPtr.Zero;
                }
            }
        }
Example #4
0
        /// <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 PTProvider instance failed to bind to the specified printer.
        /// </exception>
        /// <exception cref="PrintingNotSupportedException">
        /// Printing components are not installed on the client
        /// </exception>
        public PTProvider(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.
            uint hResult = UnsafeNativeMethods.PTOpenProviderEx(deviceName,
                                                                maxVersion,
                                                                clientVersion,
                                                                out _providerHandle,
                                                                out _schemaVersion);

            if (!PTUtility.IsSuccessCode(hResult))
            {
                throw new PrintQueueException((int)hResult, "PrintConfig.Provider.BindFail", deviceName);
            }

#if _DEBUG
            if (_schemaVersion != clientVersion)
            {
                // PTOpenProviderEx() shouldn't succeed if it can't support the requested version.
                throw new InvalidOperationException("_DEBUG: Client requested Print Schema version " +
                                                    clientVersion.ToString(CultureInfo.CurrentCulture) +
                                                    " doesn't match to provider Print Schema version " +
                                                    _schemaVersion.ToString(CultureInfo.CurrentCulture));
            }
#endif

            // If succeeded, PTOpenProviderEx() function should ensure that a valid _providerHandle
            // is returned and the returned schemaVersion is within valid range (i.e. no greater than maxVersion)
            this._deviceName = deviceName;

            this._thread = Thread.CurrentThread;

            Toolbox.EmitEvent(EventTrace.Event.WClientDRXPTProviderEnd);
        }
Example #5
0
 // Implementation of SafeHandle's this abstract method specifies how to free the handle.
 // The boolean returned should be true for success and false if the runtime
 // should fire a SafeHandleCriticalFailure MDA (CustomerDebugProbe) if that
 // MDA is enabled.
 protected override bool ReleaseHandle()
 {
     return(PTUtility.IsSuccessCode(UnsafeNativeMethods.PTCloseProviderImpl(this.handle)));
 }
Example #6
0
        /// <summary>
        /// Converts the given PrintTicket into Win32 DEVMODE.
        /// </summary>
        /// <param name="printTicket">MemoryStream containing the XML PrintTicket.</param>
        /// <param name="baseType">Type of default DEVMODE to use as base of conversion.</param>
        /// <param name="scope">scope that the input PrintTicket will be limited to</param>
        /// <returns>Byte buffer that contains the converted Win32 DEVMODE.</returns>
        /// <exception cref="ObjectDisposedException">
        /// The PTProvider instance has already been disposed.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The PrintTicket specified by <paramref name="printTicket"/> is not well-formed.
        /// </exception>
        /// <exception cref="PrintQueueException">
        /// The PTProvider instance failed to convert the PrintTicket to a DEVMODE.
        /// </exception>
        /// <exception cref="PrintingNotSupportedException">
        /// Printing components are not installed on the client
        /// </exception>
        public override byte[] ConvertPrintTicketToDevMode(MemoryStream printTicket,
                                                           BaseDevModeType baseType,
                                                           PrintTicketScope scope)
        {
            VerifyAccess();

            uint   hResult  = 0;
            string errorMsg = null;

            IntPtr umDevMode = IntPtr.Zero;

            try
            {
                IStream printTicketStream = IStreamFromMemoryStream(printTicket);
                try
                {
                    uint umDevModeLen = 0;
                    hResult = UnsafeNativeMethods.PTConvertPrintTicketToDevMode(_providerHandle,
                                                                                printTicketStream,
                                                                                (uint)baseType,
                                                                                (uint)scope,
                                                                                out umDevModeLen,
                                                                                out umDevMode,
                                                                                out errorMsg);

                    if (PTUtility.IsSuccessCode(hResult))
                    {
                        byte[] devMode = new byte[umDevModeLen];
                        Marshal.Copy(umDevMode, devMode, 0, (int)umDevModeLen);
                        return(devMode);
                    }
                }
                finally
                {
                    DeleteIStream(ref printTicketStream);
                }
            }
            finally
            {
                if (umDevMode != IntPtr.Zero)
                {
                    UnsafeNativeMethods.PTReleaseMemory(new HandleRef(this, umDevMode));
                    umDevMode = IntPtr.Zero;
                }
            }

            if ((hResult == (uint)NativeErrorCode.E_XML_INVALID) ||
                (hResult == (uint)NativeErrorCode.E_PRINTTICKET_FORMAT))
            {
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
                                                          "{0} {1} {2}",
                                                          PrintSchemaTags.Framework.PrintTicketRoot,
                                                          PTUtility.GetTextFromResource("FormatException.XMLNotWellFormed"),
                                                          errorMsg),
                                            "printTicket");
            }

            throw new PrintQueueException((int)hResult,
                                          "PrintConfig.Provider.PT2DevModeFail",
                                          _deviceName,
                                          errorMsg);
        }
Example #7
0
        /// <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>
        /// <exception cref="PrintingNotSupportedException">
        /// Printing components are not installed on the client
        /// </exception>
        public override MemoryStream MergeAndValidatePrintTicket(MemoryStream basePrintTicket,
                                                                 MemoryStream deltaPrintTicket,
                                                                 PrintTicketScope scope,
                                                                 out ConflictStatus conflictStatus)
        {
            VerifyAccess();

            conflictStatus = ConflictStatus.NoConflict;

            IStream validatedPrintTicketStream = CreateStreamOnHGlobal();

            try
            {
                IStream baseTicketStream = IStreamFromMemoryStream(basePrintTicket);
                try
                {
                    IStream deltaTicketStream = IStreamFromMemoryStream(deltaPrintTicket);
                    try
                    {
                        string errorMsg;
                        uint   hResult = UnsafeNativeMethods.PTMergeAndValidatePrintTicket(_providerHandle,
                                                                                           baseTicketStream,
                                                                                           deltaTicketStream,
                                                                                           (uint)scope,
                                                                                           validatedPrintTicketStream,
                                                                                           out errorMsg);

                        if (PTUtility.IsSuccessCode(hResult))
                        {
                            // convert the success hResult to an enum value
                            switch (hResult)
                            {
                            case (uint)NativeErrorCode.S_PT_CONFLICT_RESOLVED:
                            {
                                conflictStatus = ConflictStatus.ConflictResolved;
                                break;
                            }

                            case (uint)NativeErrorCode.S_PT_NO_CONFLICT:
                            {
                                conflictStatus = ConflictStatus.NoConflict;
                                break;
                            }

                            default:
                            {
                                throw new PrintQueueException((int)hResult,
                                                              "PrintConfig.Provider.MergeValidateFail",
                                                              _deviceName);
                            }
                            }

                            RewindIStream(validatedPrintTicketStream);

                            return(MemoryStreamFromIStream(validatedPrintTicketStream));
                        }

                        if ((hResult == (uint)NativeErrorCode.E_PRINTTICKET_FORMAT) ||
                            (hResult == (uint)NativeErrorCode.E_DELTA_PRINTTICKET_FORMAT))
                        {
                            throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
                                                                      "{0} {1} {2}",
                                                                      PrintSchemaTags.Framework.PrintTicketRoot,
                                                                      PTUtility.GetTextFromResource("FormatException.XMLNotWellFormed"),
                                                                      errorMsg),
                                                        (hResult == (uint)NativeErrorCode.E_PRINTTICKET_FORMAT) ? "basePrintTicket" : "deltaPrintTicket");
                        }
                        else
                        {
                            throw new PrintQueueException((int)hResult,
                                                          "PrintConfig.Provider.MergeValidateFail",
                                                          _deviceName,
                                                          errorMsg);
                        }
                    }
                    finally
                    {
                        DeleteIStream(ref deltaTicketStream);
                    }
                }
                finally
                {
                    DeleteIStream(ref baseTicketStream);
                }
            }
            finally
            {
                DeleteIStream(ref validatedPrintTicketStream);
            }
        }